diff -r 000000000000 -r 094583676ce7 PECengine/PresenceManager2/SrcAttribute/CPEngPresenceNotifier2Imp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PECengine/PresenceManager2/SrcAttribute/CPEngPresenceNotifier2Imp.cpp Thu Dec 17 08:41:52 2009 +0200 @@ -0,0 +1,655 @@ +/* +* Copyright (c) 2004 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: Notifier implementation to listen presence changes. +* +*/ + +// INCLUDE FILES +#include "CPEngPresenceNotifier2Imp.h" +#include "CPEngTrackedPresenceIDCollection.h" +#include "CPEngTrackedPresenceIDEntry.h" +#include "CPEngNWSessionSlotID2.h" + +#include "TPEngMDesCArrayAdapter.h" +#include "TPEngGenArrayAdapter.h" +#include "GenObserverNotifyMediators.h" + +#include "CPEngNWSessionSlotStorageProxy.h" +#include "MPEngPresenceAttrManager.h" +#include "PEngAttrLibFactory.h" + +#include "MPEngStorageManagerWatcher.h" +#include "PEngStorageManager.h" + +#include +#include +#include +#include +#include "PresenceDebugPrint.h" +#include "PEngWVPresenceAttributes2.h" + + + + +// ============================ MEMBER FUNCTIONS =============================== + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::NewL() +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CPEngPresenceNotifier2Imp* CPEngPresenceNotifier2Imp::NewL( + CPEngPresenceNotifier2& aInterface, + TInt aPriority, + const CPEngNWSessionSlotID2& aNWSessionSlotID ) + { + CPEngPresenceNotifier2Imp* self = + new ( ELeave ) CPEngPresenceNotifier2Imp( aInterface, aPriority ); + CleanupStack::PushL( self ); + self->ConstructL( aNWSessionSlotID ); + CleanupStack::Pop( self ); + return self; + } + + + +// Destructor +CPEngPresenceNotifier2Imp::~CPEngPresenceNotifier2Imp() + { + iDying = ETrue; + + Stop(); + + + if ( iWatcher ) + { + iWatcher->UnregisterListenSIDsObserver( *this ); + iWatcher->Close(); + } + + if ( iAttrManager ) + { + iAttrManager->Close(); + } + + iObsArray.Close(); + delete iUsedSlot; + delete iTrackedPresenceIDs; + iTrackedAttributes.Reset(); + } + + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::CPEngPresenceNotifier2Imp +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CPEngPresenceNotifier2Imp::CPEngPresenceNotifier2Imp( + CPEngPresenceNotifier2& aInterface, + TInt aPriority ) + : iInterface( aInterface ), + iCActivePriority( aPriority ) + { + } + + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::ConstructL() +// ----------------------------------------------------------------------------- +// +void CPEngPresenceNotifier2Imp::ConstructL( + const CPEngNWSessionSlotID2& aNWSessionSlotID ) + { + iUsedSlot = CPEngNWSessionSlotStorageProxy::NewL( aNWSessionSlotID ); + iWatcher = PEngStorageManager::GetStorageManagerWatcherL( iUsedSlot->BaseId() ); + iAttrManager = PEngAttrLibFactory::AttributeManagerInstanceL( iUsedSlot->BaseId() ); + + + iTrackedPresenceIDs = CPEngTrackedPresenceIDCollection::NewL(); + } + + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::IsActive() +// ----------------------------------------------------------------------------- +// +TBool CPEngPresenceNotifier2Imp::IsActive() const + { + return iStarted; + } + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::Start() +// ----------------------------------------------------------------------------- +// +TInt CPEngPresenceNotifier2Imp::Start( const MDesCArray& aPresenceIDs, + const TArray& aTypes ) + { + //sanity checks to encapsulate notifier behaviour + if ( iDying ) + { + //if dying, the notifier restart is silently ignored + //because notifier is evidently shutting down + return KErrNone; + } + + if ( iStarted ) + { + return KErrInUse; + } + + + CDesCArray* sidsList = NULL; + TRAPD( err, + { + //Generate SIDs + //Generating ignores duplicate attributes and presence IDs + GenerateSidsL( sidsList, aPresenceIDs ); + + + //Add the ID & attributes to notify collection + //Adding ignores duplicate attributes and presence IDs + iTrackedPresenceIDs->AddTrackedIdsL( aPresenceIDs, aTypes ); + + + //Cache tracked attribute types + //Adding ignores duplicate attributes + AddTrackedAttributesL( aTypes ); + + + //and register for SID change events + iWatcher->RegisterListenSIDsObserverL( + *sidsList, + *this, + MPEngStorageManagerWatcher::EPEngObserverNormalPriority, + EFalse ); + } ); + + delete sidsList; + + if ( err == KErrNone ) + { + iStarted = ETrue; + } + + else + { + //Cancel the notification requests + iTrackedPresenceIDs->RemoveAllTrackedIds(); + iWatcher->UnregisterListenSIDsObserver( *this ); + iTrackedAttributes.Reset(); + } + + return err; + } + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::Stop() +// ----------------------------------------------------------------------------- +// +void CPEngPresenceNotifier2Imp::Stop() + { + //if not running, nothing to do + if ( !iStarted ) + { + return; + } + + + // The state must be set to stopped before actual stopping to + // prevent unintentional event leaks. + iStarted = EFalse; + + //Cancel the notification requests + iWatcher->RestartSIDsObserver( *this ); + + //Reset cached arrays + iTrackedPresenceIDs->RemoveAllTrackedIds(); + iTrackedAttributes.Reset(); + } + + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::Update() +// ----------------------------------------------------------------------------- +// +TInt CPEngPresenceNotifier2Imp::Update( const MDesCArray& aPresenceIDs, + const TArray* aTypes, + TBool aKeepOldTrackeds ) + { + if ( !iStarted ) + { + return KErrNotReady; + } + + TArray trackedAttributesLocal = iTrackedAttributes.Array(); + if ( !aTypes ) + { + aTypes = &trackedAttributesLocal; + } + + + CDesCArray* sidsList = NULL; + TRAPD( err, UpdateWatcherL( sidsList, + aPresenceIDs, + *aTypes, + aKeepOldTrackeds ) ); + + //If there isn't sidsList, the add has failed totally + //and there isn't a need to tidy the list or watcher + if ( ( err != KErrNone ) && sidsList ) + { + // if aKeepOldTrackeds was not active, no need to clean tracked ids + if ( aKeepOldTrackeds ) + { + iTrackedPresenceIDs->RemoveTrackedIds( aPresenceIDs, *aTypes ); + } + iWatcher->RemoveSIDsFromSIDsObserver( *sidsList, *this ); + } + + delete sidsList; + return err; + } + + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::Remove() +// ----------------------------------------------------------------------------- +// +TInt CPEngPresenceNotifier2Imp::Remove( const TDesC& aPresenceID ) + { + if ( !iStarted ) + { + return KErrNotReady; + } + + + const CPEngTrackedPresenceIDEntry* trackedID = + iTrackedPresenceIDs->FindTrackedPresenceID( aPresenceID ); + if ( !trackedID ) + { + return KErrNotFound; + } + + + TPEngMDesCArrayAdapter presenceIdAdapter( aPresenceID ); + CDesCArray* sidsList = NULL; + TRAPD( err, + GenerateSidsL( sidsList, presenceIdAdapter ) ); + if ( err != KErrNone ) + { + delete sidsList; + return err; + } + + + //No exceptions allowed below... + iTrackedPresenceIDs->RemoveTrackedIds( presenceIdAdapter ); + iWatcher->RemoveSIDsFromSIDsObserver( *sidsList, *this ); + delete sidsList; + + return KErrNone; + } + + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::Remove() +// ----------------------------------------------------------------------------- +// +TInt CPEngPresenceNotifier2Imp::Remove( TUint32 aType ) + { + if ( !iStarted ) + { + return KErrNotReady; + } + + + //Gather first a filtered list of presence ID's that have + //attribute as tracked + iTrackedPresenceIDs->ResetFilteredList(); + const TInt trackedCount = iTrackedPresenceIDs->TrackedPresenceIDsCount(); + for ( TInt trackedIx = 0; trackedIx < trackedCount; trackedIx++ ) + { + const CPEngTrackedPresenceIDEntry& trackedID = + iTrackedPresenceIDs->TrackedPresenceID( trackedIx ); + + if ( trackedID.IsOnlyTrackedAttribute( aType ) ) + { + iTrackedPresenceIDs->IncludeToFilteredList( trackedIx ); + } + } + + //Gather list of SIDs to unregister + CDesCArray* sidsList = NULL; + + const MDesCArray& filteredList = iTrackedPresenceIDs->FilteredList(); + TPEngGenArrayAdapter< TUint32 > attrTypeAdapter( aType ); + //if( filteredList.MdcaCount() > 0 ) + { + TRAPD( err, + GenerateSidsL( sidsList, + filteredList ) ); + if ( err != KErrNone ) + { + return err; + } + } + + + //List of to be removed SIDs gathered -> do the remove + //No exceptions allowed below... + + iTrackedPresenceIDs->RemoveTrackedIds( attrTypeAdapter.Array() ); + iWatcher->RemoveSIDsFromSIDsObserver( *sidsList, *this ); + delete sidsList; + + if ( RemoveTrackedAttributes( attrTypeAdapter.Array() ) ) + { + return KErrNone; + } + + return KErrNotFound; + } + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::TrackedPresenceIDs() +// ----------------------------------------------------------------------------- +// +CPEngTrackedPresenceIDs2& CPEngPresenceNotifier2Imp::TrackedPresenceIDs() + { + return iTrackedPresenceIDs->Interface(); + } + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::AddObserver() +// ----------------------------------------------------------------------------- +// +TInt CPEngPresenceNotifier2Imp::AddObserver( MPEngPresenceObserver2& aObserver ) + { + return iObsArray.AddObserver( &aObserver ); + } + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::RemoveObserver() +// ----------------------------------------------------------------------------- +// +TInt CPEngPresenceNotifier2Imp::RemoveObserver( MPEngPresenceObserver2& aObserver ) + { + return iObsArray.RemoveObserver( &aObserver ); + } + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::HandleSIDsChangeL() +// From MPEngSIDChangeObserver +// ----------------------------------------------------------------------------- +// +void CPEngPresenceNotifier2Imp::HandleSIDsChangeL( CPtrCArray& aChangedSIDs ) + { + //if not running, don't notify the observers + if ( !iStarted ) + { + return; + } + + iTrackedPresenceIDs->ResetPresenceChangeMarks(); + const TInt sidCount( aChangedSIDs.MdcaCount() ); + + PENG_DP( D_PENG_LIT( "CPEngPresenceNotifier2Imp::HandleSIDsChangeL() - %d attribute SIDs" ), + sidCount ); + + for ( TInt sidIx( 0 ); sidIx < sidCount; sidIx++ ) + { + TPtrC sid = aChangedSIDs.MdcaPoint( sidIx ); + TUint32 attribute = KPEngNullAttributeType; + TPtrC presenceId( NULL, 0 ); + TInt err = iAttrManager->ResolveStoreId( sid, attribute, presenceId ); + + if ( err == KErrNone ) + { + iTrackedPresenceIDs->MarkPresenceChange( presenceId ); + } + } + + MediateNotify( KErrNone ); + } + + + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::HandleSIDNotifyError() +// From MPEngSIDChangeObserver +// ----------------------------------------------------------------------------- +// +void CPEngPresenceNotifier2Imp::HandleSIDNotifyError( TInt aError ) + { + //if not running, don't notify the observers + if ( !iStarted ) + { + return; + } + + iTrackedPresenceIDs->ResetPresenceChangeMarks(); + MediateNotify( aError ); + } + + + + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::GenerateSidsL() +// ----------------------------------------------------------------------------- +// +void CPEngPresenceNotifier2Imp::GenerateSidsL( CDesCArray*& aGeneratedSids, + const MDesCArray& aPresenceIDs ) + { + aGeneratedSids = NULL; + + //Make sure that array granurality never gets to zero + TInt granurality = aPresenceIDs.MdcaCount(); + if ( granurality == 0 ) + { + granurality++; + } + + CDesCArrayFlat* sids = new ( ELeave ) CDesCArrayFlat( granurality ); + CleanupStack::PushL( sids ); + + const TInt presenceIdCount( aPresenceIDs.MdcaCount() ); + for ( TInt pIx( 0 ); pIx < presenceIdCount; pIx++ ) + { + TPtrC presenceID( aPresenceIDs.MdcaPoint( pIx ) ); + + // only one attribute to be observed + HBufC* theSid = iAttrManager->GenerateStoreIdL( KUidPrAttrOnlineStatus, presenceID ); + CleanupStack::PushL( theSid ); + + //This checks against duplicate PresenceIDs + //==> Ignore duplicates + TRAPD( err, sids->InsertIsqL( *theSid ) ); + if ( err != KErrAlreadyExists ) + { + User::LeaveIfError( err ); + } + + CleanupStack::PopAndDestroy( theSid ); + } + + CleanupStack::Pop( sids ); + aGeneratedSids = sids; + } + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::AddTrackedAttributesL() +// ----------------------------------------------------------------------------- +// +void CPEngPresenceNotifier2Imp::AddTrackedAttributesL( const TArray& aTypes ) + { + const TInt count = aTypes.Count(); + for ( TInt ix = 0; ix < count; ix++ ) + { + TRAPD( err, iTrackedAttributes.InsertInSignedKeyOrderL( aTypes[ ix ] ) ); + if ( err != KErrAlreadyExists ) + { + User::LeaveIfError( err ); + } + } + } + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::RemoveTrackedAttributes() +// ----------------------------------------------------------------------------- +// +TBool CPEngPresenceNotifier2Imp::RemoveTrackedAttributes( const TArray& aTypes ) + { + TBool anyRemoved = EFalse; + + const TInt count = aTypes.Count(); + for ( TInt ix = 0; ix < count; ix++ ) + { + TInt index = iTrackedAttributes.FindInSignedKeyOrder( aTypes[ ix ] ); + if ( index != KErrNotFound ) + { + iTrackedAttributes.Remove( index ); + anyRemoved = ETrue; + } + } + + return anyRemoved; + } + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::MediateNotify() +// ----------------------------------------------------------------------------- +// +void CPEngPresenceNotifier2Imp::MediateNotify( TInt aError ) + { + TPresenceNotifyMediator eventMediator( iInterface, + *iTrackedPresenceIDs ); + if ( aError == KErrNone ) + { + iObsArray.NotifyObservers( eventMediator ); + } + else + { + iObsArray.NotifyErrorObservers( eventMediator, aError ); + } + } + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::UpdateWatcherL() +// ----------------------------------------------------------------------------- +// +void CPEngPresenceNotifier2Imp::UpdateWatcherL( + CDesCArray*& aSidsList, + const MDesCArray& aPresenceIDs, + const TArray& aTypes, + TBool aKeepOldTrackeds ) + { + GenerateSidsL( aSidsList, aPresenceIDs ); + + //Update the ID & attributes to notify array + // if we should not keep old ones, use temp tracked presence ids + CPEngTrackedPresenceIDCollection* trackedIds = NULL; + if ( !aKeepOldTrackeds ) + { + trackedIds = CPEngTrackedPresenceIDCollection::NewL(); + CleanupStack::PushL( trackedIds ); + trackedIds->AddTrackedIdsL( aPresenceIDs, aTypes ); + } + else + { + iTrackedPresenceIDs->AddTrackedIdsL( aPresenceIDs, aTypes ); + } + + //And update SID change request + //aKeepOldTrackeds determines is this add or update + iWatcher->RegisterListenSIDsObserverL( *aSidsList, + *this, + MPEngStorageManagerWatcher::EPEngObserverNormalPriority, + aKeepOldTrackeds ); + + if ( trackedIds ) + { + delete iTrackedPresenceIDs; + iTrackedPresenceIDs = trackedIds; + CleanupStack::Pop( trackedIds ); + } + } + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::TPresenceNotifyMediator::TPresenceNotifyMediator() +// ----------------------------------------------------------------------------- +// +CPEngPresenceNotifier2Imp::TPresenceNotifyMediator::TPresenceNotifyMediator( + CPEngPresenceNotifier2& aNotifier, + CPEngTrackedPresenceIDCollection& aPresenceIds ) + : iNotifier( aNotifier ), + iPresenceIds( aPresenceIds ) + { + } + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::TPresenceNotifyMediator::MediateNotifyL() +// ----------------------------------------------------------------------------- +// +void CPEngPresenceNotifier2Imp::TPresenceNotifyMediator::MediateNotifyL( + MPEngPresenceObserver2& aObserverToNotify ) + { + iPresenceIds.ResetTrackedEntriesIterators(); + iPresenceIds.Interface().ResetTrackedIterator(); + iPresenceIds.Interface().ResetChangedIterator(); + + aObserverToNotify.HandlePresenceChangeL( iNotifier, iPresenceIds.Interface() ); + } + + + +// ----------------------------------------------------------------------------- +// CPEngPresenceNotifier2Imp::TPresenceNotifyMediator::MediateNotifyError() +// ----------------------------------------------------------------------------- +// +void CPEngPresenceNotifier2Imp::TPresenceNotifyMediator::MediateNotifyError( + MPEngPresenceObserver2& aObserverToNotify, + TInt aLeaveError ) + { + aObserverToNotify.HandlePresenceError( aLeaveError, iNotifier ); + } + + + +// End of File + + +