--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook2/NamesListExtension/src/CPbk2EcePresenceEngine.cpp Wed Sep 01 12:29:52 2010 +0100
@@ -0,0 +1,597 @@
+/*
+* 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:
+*
+*/
+
+
+#include "CPbk2EcePresenceEngine.h"
+
+#include <CPbk2IconArray.h>
+#include <TPbk2IconId.h>
+#include <Pbk2IconId.hrh>
+#include <Pbk2UID.h>
+#include <MPbk2ContactUiControlUpdate.h>
+#include <MVPbkViewContact.h>
+#include <MVPbkContactLink.h>
+#include <CVPbkContactManager.h>
+#include <cbsfactory.h>
+#include <contactpresencebrandids.h>
+#include <mbsaccess.h>
+#include <spsettings.h>
+#include <spproperty.h>
+
+//ECE
+#include "CPbk2UIExtensionInformation.h"
+#include <CPbk2UIExtensionPlugin.h>
+#include <Pbk2UIExtension.hrh>
+#include <TPbk2IconId.h>
+#include "Pbk2NamesListExUID.h"
+#include <gulicon.h>
+#include <fbs.h>
+
+#include <contactpresencefactory.h>
+#include <mcontactpresence.h>
+/// Unnamed namespace for local definitions
+namespace {
+
+enum TNlxPanicCodes
+ {
+ ENlxPanicEmptyPackage,
+ ENlxPanicIconNull,
+ ENlxPanicNoIconInfo,
+ ENlxPanicNoIcons,
+ ENlxPanicNoLinks,
+ ENlxPanicStrayIcon,
+ ENlxPanicStrayIconInfo
+ };
+
+_LIT(KPanicText, "CPbk2EcePresenceEngine");
+
+void Panic(TNlxPanicCodes aReason)
+ {
+ _LIT( KPanicText, "CPbk2_nlx" );
+ User::Panic(KPanicText,aReason);
+ }
+
+} /// namespace
+
+const TInt KEcePresFirstIconId = 1000;
+const TInt KEcePresLastIconId = 2000;
+// The maximum number of icons infos that are kept live
+const TInt KEceMaxIconInfoCashe = 100;
+/// The maximum number of subscriptions that are kept live.
+const TInt KEceMaxSubscriptionsCached = 20;
+
+// -----------------------------------------------------------------------------
+// CPbk2EcePresenceEngine::NewL
+// -----------------------------------------------------------------------------
+//
+CPbk2EcePresenceEngine* CPbk2EcePresenceEngine::NewL(
+ CVPbkContactManager& aContactManager,
+ MPbk2EcePresenceEngineObserver& aObserver,
+ TSize aIconSize )
+ {
+ CPbk2EcePresenceEngine* self =
+ new ( ELeave ) CPbk2EcePresenceEngine( aContactManager, aObserver, aIconSize );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CPbk2EcePresenceEngine::~CPbk2EcePresenceEngine
+// -----------------------------------------------------------------------------
+//
+CPbk2EcePresenceEngine::~CPbk2EcePresenceEngine()
+ {
+ if ( iPresenceClient )
+ {
+ iPresenceClient->Close();
+ }
+ delete iSubscriptionMonitor;
+ iSubscriptions.ResetAndDestroy();
+ iIconInfoArray.ResetAndDestroy();
+ }
+
+// -----------------------------------------------------------------------------
+// CPbk2EcePresenceEngine::CPbk2EcePresenceEngine
+// -----------------------------------------------------------------------------
+//
+CPbk2EcePresenceEngine::CPbk2EcePresenceEngine
+ (
+ CVPbkContactManager& aContactManager,
+ MPbk2EcePresenceEngineObserver& aObserver,
+ TSize aIconSize ) :
+ iContactManager( aContactManager ),
+ iObserver( aObserver ),
+ iIconSize( aIconSize )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CPbk2EcePresenceEngine::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CPbk2EcePresenceEngine::ConstructL()
+ {
+ iPresenceClient = TContactPresenceFactory::NewContactPresenceL( iContactManager, *this );
+
+ iNextIconId = KEcePresFirstIconId;
+ iSubscriptionMonitor = CIdle::NewL(CActive::EPriorityIdle);
+ }
+
+void CPbk2EcePresenceEngine::SubscribeContactPresenceL( const MVPbkContactLink& aLink )
+ {
+ CPbk2NlxPresenceSubscriptionInfo* subscriptionInfo = FindSubscription( aLink );
+
+ if ( !subscriptionInfo )
+ {
+ // This contact is not observed yet.
+ // Costruct our own placeholder for information about this request
+ MVPbkContactLink* link = aLink.CloneLC();
+ subscriptionInfo = CPbk2NlxPresenceSubscriptionInfo::NewL(
+ link ); // takes ownership of link
+ CleanupStack::Pop(); // link
+ CleanupStack::PushL( subscriptionInfo );
+ User::LeaveIfError( iSubscriptions.Append( subscriptionInfo ) );
+ CleanupStack::Pop( subscriptionInfo );
+
+ if(!iSubscriptionMonitor->IsActive())
+ {
+ iSubscriptionMonitor->Start(TCallBack(CPbk2EcePresenceEngine::SubscriptionMonitorL, this));
+ }
+ }
+ CleanUpOldSubscriptionsL();
+ }
+
+TBool CPbk2EcePresenceEngine::GetIconIdForContact(
+ const MVPbkContactLink& aLink,
+ TPbk2IconId& aIconId )
+ {
+ // Do we have an icon NOW?
+ CPbk2NlxPresenceSubscriptionInfo* subscriptionInfo = FindSubscription( aLink );
+ TBool hasIcon = EFalse;
+ if ( subscriptionInfo )
+ {
+ // We have subscribed for the presence of this contact.
+ const CPbk2NlxPresenceIconInfo* iconInfo = subscriptionInfo->IconInfo();
+ // But do we have an icon for it?
+ if ( iconInfo )
+ {
+ if ( iconInfo->Bitmap() && iconInfo->BitmapMask() )
+ {
+ // We have received the icon information for this contact and the actual icons.
+ TPbk2IconId iconId( TUid::Uid( KPbk2UID3 ), iconInfo->IconId() );
+ aIconId = iconId;
+ hasIcon = ETrue;
+ }
+ }
+ }
+ return hasIcon;
+ }
+
+CGulIcon* CPbk2EcePresenceEngine::CreateIconCopyLC( const TPbk2IconId& aIconId )
+ {
+ CPbk2NlxPresenceIconInfo* iconInfo = FindIconInfo( aIconId );
+ __ASSERT_DEBUG( iconInfo , Panic( ENlxPanicNoIconInfo ) );
+ __ASSERT_ALWAYS( iconInfo , User::Leave( KErrGeneral ) );
+ // According to the contract of GetIconIdForContact(), it returns ETrue
+ // only if the actual icons exist.
+ __ASSERT_DEBUG( iconInfo->Bitmap() && iconInfo->BitmapMask(),
+ Panic( ENlxPanicNoIcons ) );
+ __ASSERT_ALWAYS( iconInfo->Bitmap() && iconInfo->BitmapMask(),
+ User::Leave( KErrGeneral ) );
+
+ CFbsBitmap* newBitmap = NULL;
+ CFbsBitmap* newBitmapMask = NULL;
+
+ TLanguage brandingLang = FindBrandLanguageIdL(iconInfo->BrandId());
+
+ TLanguage userLang = User::Language();
+ TLanguage defaultLang = ELangInternationalEnglish;
+ CBSFactory* brandingFactory = CBSFactory::NewL(KCPBrandDefaultId, KCPBrandAppId );
+ CleanupStack::PushL( brandingFactory );
+
+ ////
+ //Search for BrandPackage using PhoneLanguage
+ //PhoneLanguage gets the Highest Priority
+ TRAPD( err, GetBitmapFromBrandingServerL( userLang, newBitmap, newBitmapMask, *brandingFactory, iconInfo->BrandId(), iconInfo->ElementId() ) );
+
+ if ( err && ( userLang != brandingLang ) )
+ {
+ //The next priority goes to BrandLanguage set in the SpSettings/service table
+ //during provisioning
+ //Search for BrandPackage using this BrandLanguage
+ TRAP( err, GetBitmapFromBrandingServerL( brandingLang, newBitmap, newBitmapMask, *brandingFactory, iconInfo->BrandId(), iconInfo->ElementId()));
+ }
+
+ if ( err && ( brandingLang != defaultLang ) && ( userLang != defaultLang ) )
+ {
+ //The least priority goes to the default language which is ELangInternationalEnglish
+ //Search for BrandPackage using this ELangInternationalEnglish
+ GetBitmapFromBrandingServerL( defaultLang, newBitmap, newBitmapMask, *brandingFactory, iconInfo->BrandId(), iconInfo->ElementId() ) ;
+ }
+ ////
+ CleanupStack::PopAndDestroy( brandingFactory );
+ CGulIcon* gulIcon = CGulIcon::NewL( newBitmap, newBitmapMask );
+ CleanupStack::PushL( gulIcon );
+ return gulIcon;
+ }
+
+void CPbk2EcePresenceEngine::GetBitmapFromBrandingServerL(
+ TLanguage aLanguageId,
+ CFbsBitmap*& aBrandedBitmap,
+ CFbsBitmap*& aBrandedMask,
+ CBSFactory& aBSFactory,
+ const TDesC8& aBrandId,
+ const TDesC8& aElementId)
+ {
+ MBSAccess* brandingAccess = aBSFactory.CreateAccessLC(
+ aBrandId, aLanguageId );
+
+ if ( aBrandId.Length() )
+ {
+ brandingAccess->GetBitmapL( aElementId, aBrandedBitmap, aBrandedMask );
+ }
+
+ CleanupStack::PopAndDestroy(); //access
+ }
+
+
+TLanguage CPbk2EcePresenceEngine::FindBrandLanguageIdL( const TDesC8& aBrandId )
+ {
+ const TInt KMaxBufLength = 512;
+ CSPSettings* spSettings = CSPSettings::NewLC();
+ RIdArray idArray;
+ CleanupClosePushL(idArray);
+ User::LeaveIfError(spSettings->FindServiceIdsL(idArray));
+ CSPProperty* prop = CSPProperty::NewLC();
+ HBufC* brandID = HBufC::NewLC(KMaxBufLength);
+ TLanguage servLang = ELangInternationalEnglish;
+ TInt serviceCount = idArray.Count();
+
+ //The challenge here is to find the ServiceTable entry using BrandId.
+ //Iterate thro each service id and find the BrandId
+ //for each service and check whether it matches to out Input BrandId.
+ //if it matches we have found the service, and now
+ //get the brandlanguage.
+ //Note : The problem with this logic is that it works only
+ // if all the services brandid is unique.
+ // If not GOD needs to help us.
+ // This logic is a temporary one untill
+ // one of our CR for Changing the Interface, so that you
+ // get the BrandLanguage as part of the StartGetIconInfoL
+ // is approved.
+ //
+ for (TInt index=0; index<serviceCount; index++)
+ {
+ if ( KErrNone == spSettings->FindPropertyL( idArray[index], EPropertyBrandId, *prop ) )
+ {
+ TPtr des = brandID->Des();
+ if ( KErrNone == prop->GetValue( des ) )
+ {
+ TBuf8 <KMaxBufLength> brandIdFromSpSettings;
+ brandIdFromSpSettings.Copy(des);
+ if ( KErrNone == brandIdFromSpSettings.Compare( aBrandId ) )
+ {
+ if( KErrNone == spSettings->FindPropertyL(
+ idArray[index], EPropertyBrandLanguage, *prop) )
+ {
+ prop->GetValue( ( TInt& )servLang );
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy( 4 ); //brandID, prop, idArray, spSettings
+
+ return servLang;
+ }
+
+void CPbk2EcePresenceEngine::ReceiveIconInfoL(
+ const TDesC8& aPackedLink, const TDesC8& aBrandId, const TDesC8& aElementId )
+ {
+ __ASSERT_DEBUG( aPackedLink.Length() > 0, Panic( ENlxPanicEmptyPackage) );
+ __ASSERT_ALWAYS( aPackedLink.Length() > 0, User::Leave( KErrGeneral ) );
+
+ // Unpack the link array
+ CVPbkContactLinkArray* linkArray =
+ CVPbkContactLinkArray::NewLC( aPackedLink, iContactManager.ContactStoresL() );
+ __ASSERT_DEBUG( linkArray->Count() > 0, Panic( ENlxPanicNoLinks) );
+ __ASSERT_ALWAYS( linkArray->Count() > 0, User::Leave( KErrGeneral ) );
+ const MVPbkContactLink& link = linkArray->At( 0 ); // There is icon info for just one contact.
+
+ // Find the corresponding contact info
+ CPbk2NlxPresenceSubscriptionInfo* subscriptionInfo = FindSubscription( link );
+ __ASSERT_DEBUG( subscriptionInfo, Panic( ENlxPanicStrayIconInfo) );
+ if ( subscriptionInfo )
+ {
+ // Check to see if we already have a placeholder object for this icon ID.
+ CPbk2NlxPresenceIconInfo* iconInfo = FindIconInfo( aBrandId, aElementId );
+ if ( !iconInfo )
+ {
+ // No placeholder exists yet. This is the first time that we heard
+ // of this icon. Create an object to hold the icon and its ID information.
+ // (we don't have the actual icon yet)
+ iconInfo = CPbk2NlxPresenceIconInfo::NewLC( aBrandId, aElementId, iNextIconId );
+ User::LeaveIfError( iIconInfoArray.Append( iconInfo ) );
+ CleanupStack::Pop( iconInfo );
+ ++iNextIconId;
+ if ( iNextIconId > KEcePresLastIconId )
+ {
+ iNextIconId = KEcePresFirstIconId;
+ }
+
+ // Request the icon. It will arrive later through ReceiveIconFileL().
+ iPresenceClient->GetPresenceIconFileL( aBrandId, aElementId );
+ }
+
+ // Create a mapping from subscriptionInfo to iconInfo.
+ subscriptionInfo->SetIconInfo( iconInfo ); // ownership not transferred
+
+ // Inform Phonebook UI that contact needs to be redrawn
+ iObserver.ContactPresenceChanged( subscriptionInfo->ContactLink() );
+ }
+ else
+ {
+ // It was a stray contact info which we didn't request.
+ }
+ CleanupStack::PopAndDestroy( linkArray );
+ }
+
+void CPbk2EcePresenceEngine::ReceiveIconFileL(
+ const TDesC8& aBrandId,
+ const TDesC8& aElementId,
+ CFbsBitmap* aBrandedBitmap,
+ CFbsBitmap* aMask )
+ {
+ // __ASSERT_DEBUG( aBrandedBitmap && aMask, Panic( ENlxPanicIconNull) );
+ // __ASSERT_ALWAYS( aBrandedBitmap && aMask, User::Leave( KErrGeneral ) );
+ // Find the corresponding icon info
+ CPbk2NlxPresenceIconInfo* iconInfo = FindIconInfo( aBrandId, aElementId );
+
+ if ( iconInfo )
+ {
+ iconInfo->SetIcons( aBrandedBitmap, aMask ); // takes ownership
+
+ InformObserverOfContactChanges( aBrandId, aElementId );
+ }
+ else
+ {
+ // It was a stray icon which we didn't request.
+ delete aBrandedBitmap;
+ delete aMask;
+ }
+ }
+
+void CPbk2EcePresenceEngine::ReceiveIconInfosL(
+ const TDesC8& /*aPackedLink*/,
+ RPointerArray <MContactPresenceInfo>& /*aInfoArray*/,
+ TInt /*aOpId*/ )
+ {
+ }
+
+void CPbk2EcePresenceEngine::InformObserverOfContactChanges(
+ const TDesC8& aBrandId,
+ const TDesC8& aElementId )
+ {
+ // Tell observer that the UI needs to be refreshed
+ // Loop through all subscriptions and check which ones have a matching icon.
+ for ( TInt n = 0; n < iSubscriptions.Count(); ++n )
+ {
+ CPbk2NlxPresenceSubscriptionInfo* subscr = iSubscriptions[n];
+ if ( subscr->IconInfo() )
+ {
+ if ( subscr->IconInfo()->BrandId().Compare( aBrandId ) == 0 &&
+ subscr->IconInfo()->ElementId().Compare( aElementId ) == 0 )
+ {
+ // The icon matches
+ // Inform Phonebook about this contact
+ iObserver.ContactPresenceChanged( subscr->ContactLink() );
+ }
+ }
+ }
+ }
+
+/**
+ * Find a contact watching info object.
+ * @return The object, or NULL if not found.
+ */
+CPbk2NlxPresenceSubscriptionInfo* CPbk2EcePresenceEngine::FindSubscription(
+ const MVPbkContactLink& aContactLink )
+ {
+ CPbk2NlxPresenceSubscriptionInfo* info = NULL;
+ TInt count = iSubscriptions.Count();
+ for ( TInt n = 0; n < count && !info; ++n )
+ {
+ CPbk2NlxPresenceSubscriptionInfo* tmpInfo = iSubscriptions[n];
+ if ( tmpInfo->ContactLink().IsSame( aContactLink ) )
+ {
+ // The info was found
+ info = tmpInfo;
+ }
+ }
+ return info;
+ }
+
+/**
+ * Find an icon info object.
+ * @return The object, or NULL if not found.
+ */
+CPbk2NlxPresenceIconInfo* CPbk2EcePresenceEngine::FindIconInfo(
+ const TDesC8& aBrandId,
+ const TDesC8& aElementId )
+ {
+ CPbk2NlxPresenceIconInfo* info = NULL;
+ TInt count = iIconInfoArray.Count();
+ for ( TInt n = 0; n < count && !info; ++n )
+ {
+ CPbk2NlxPresenceIconInfo* tmpInfo = iIconInfoArray[n];
+ if ( tmpInfo->BrandId().Compare( aBrandId ) == 0
+ && tmpInfo->ElementId().Compare( aElementId ) == 0 )
+ {
+ // The icon info was found
+ info = tmpInfo;
+ }
+ }
+ return info;
+ }
+
+/**
+ * Find an icon info object.
+ *
+ * @todo The UID part of the icon ID is ignored currently.
+ * @return The object, or NULL if not found.
+ */
+CPbk2NlxPresenceIconInfo* CPbk2EcePresenceEngine::FindIconInfo( const TPbk2IconId& aIconId )
+ {
+ CPbk2NlxPresenceIconInfo* info = NULL;
+ TInt count = iIconInfoArray.Count();
+ for ( TInt n = 0; n < count && !info; ++n )
+ {
+ CPbk2NlxPresenceIconInfo* tmpInfo = iIconInfoArray[n];
+ // Create a temporary pbk icon id for comparison purposes
+ TPbk2IconId iconId( TUid::Uid( KPbk2UID3 ), tmpInfo->IconId() );
+ if ( iconId == aIconId )
+ {
+ // The icon info was found
+ info = tmpInfo;
+ }
+ }
+ return info;
+ }
+
+void CPbk2EcePresenceEngine::CleanUpOldSubscriptionsL()
+ {
+ // Unsubscribe the oldest excess subscriptions
+ const TInt count = iSubscriptions.Count();
+ // Loop through the excess subscriptions, starting from the oldest
+ for ( TInt n = count - 1; n >= KEceMaxSubscriptionsCached; --n )
+ {
+ CPbk2NlxPresenceSubscriptionInfo* subscr = iSubscriptions[KEceMaxSubscriptionsCached-n];
+
+ // Construct a package that contains the link.
+ CDesC8ArrayFlat* desArray = new (ELeave) CDesC8ArrayFlat( 2 ); // granularity of 2
+ CleanupStack::PushL( desArray );
+ HBufC8* packedLink = subscr->ContactLink().PackLC();
+ desArray->AppendL( *packedLink );
+ CleanupStack::PopAndDestroy( packedLink );
+ if(subscr->IsSubscribed())
+ {
+ iPresenceClient->CancelSubscribePresenceInfo( *desArray );
+ }
+ CleanupStack::PopAndDestroy( desArray );
+
+ iSubscriptions.Remove( 0 );
+ delete subscr;
+ }
+ }
+
+void CPbk2EcePresenceEngine::CleanUpExtraIcons()
+ {
+ const TInt subscriptionsCount = iSubscriptions.Count();
+ TInt iconCount = iIconInfoArray.Count();
+ CPbk2NlxPresenceIconInfo* iconinfo = NULL;
+ CPbk2NlxPresenceSubscriptionInfo* subscriptionInfo = NULL;
+
+ for (TInt i=0; i<iconCount; i++)
+ {
+ TBool found = EFalse;
+ iconinfo = iIconInfoArray[i];
+
+ for (TInt j=0; j<subscriptionsCount; j++)
+ {
+ subscriptionInfo = iSubscriptions[j];
+ if(iconinfo == subscriptionInfo->IconInfo())
+ {
+ found = ETrue;
+ }
+ }
+ if(!found)
+ {
+ iIconInfoArray.Remove(i);
+ delete iconinfo;
+ i--;
+ iconCount--;
+ }
+ }
+ }
+
+CFbsBitmap* CPbk2EcePresenceEngine::CloneBitmapL( const CFbsBitmap& aOriginalBitmap )
+ {
+ CFbsBitmap* newBitmap = new (ELeave) CFbsBitmap;
+ newBitmap->Duplicate(aOriginalBitmap.Handle());
+ return newBitmap;
+ }
+void CPbk2EcePresenceEngine::PresenceSubscribeError(
+ const TDesC8& aContactLink,
+ TInt aStatus )
+ {
+ }
+
+void CPbk2EcePresenceEngine::ErrorOccured(
+ TInt aOpId,
+ TInt aStatus )
+ {
+ }
+TInt CPbk2EcePresenceEngine::SubscriptionMonitorL(TAny* aPtr)
+ {
+ CPbk2EcePresenceEngine* ptr = (CPbk2EcePresenceEngine*) aPtr;
+ TInt result = ptr->SubscriptionMonitorL();
+ return result;//if False, CIdle ends loop
+ }
+TInt CPbk2EcePresenceEngine::SubscriptionMonitorL()
+ {
+ const TInt StepGranularity = 1;
+ const TInt count = iSubscriptions.Count();
+ CPbk2NlxPresenceSubscriptionInfo* subscriptionInfo=NULL;
+ TInt progress=0;
+ TInt n=count;
+ // Loop through the excess subscriptions, starting from the newest
+ while(n>0 && progress<StepGranularity)
+ {
+ n--;
+ subscriptionInfo = iSubscriptions[n];
+
+ if(!subscriptionInfo->IsSubscribed())
+ {
+ // Construct a package that contains the link.
+ CDesC8ArrayFlat* desArray = new (ELeave) CDesC8ArrayFlat( 2 ); // granularity of 2
+ CleanupStack::PushL( desArray );
+
+ HBufC8* packedLink = subscriptionInfo->ContactLink().PackLC();
+ desArray->AppendL( *packedLink );
+ CleanupStack::PopAndDestroy( packedLink );
+
+ iPresenceClient->SetPresenceIconSize( iIconSize );
+ iPresenceClient->SubscribePresenceInfoL( *desArray );
+ CleanupStack::PopAndDestroy( desArray );
+ // The results will arrive through the observer interface - ReceiveIconInfoL().
+ subscriptionInfo->Subscribed();
+ progress++;
+ }
+ }
+
+ if(iIconInfoArray.Count() > KEceMaxIconInfoCashe)
+ {
+ CleanUpExtraIcons();
+ }
+ return progress;
+ }
+
+// End of File