--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/contextutility/src/hgcontextutilityimpl.cpp Thu Dec 17 08:54:17 2009 +0200
@@ -0,0 +1,972 @@
+/*
+* Copyright (c) 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: Context publishing helper dll
+*
+*/
+
+
+#include <cfcontextobject.h>
+#include <cfclient.h>
+#include <mdesession.h>
+#include <mdeobject.h>
+#include <s32mem.h>
+#include <MVPbkContactLink.h>
+#include <MVPbkStoreContact.h>
+#include <MVPbkStreamable.h>
+#include <CVPbkContactLinkArray.h>
+#include <e32debug.h>
+#include <w32std.h>
+#include "hgcontextutilityimpl.h"
+#include "hgcontexttypes.h"
+
+// max number of entries processed when aContextData is an array in PublishContextL
+const TInt KMaxEntriesInMulti = 20;
+
+// separator character in combined string for multiple entries
+const TInt KMultiSepChar = 0x0001;
+
+// granularity for string array
+const TInt KArrayGranularity = 4;
+
+// argument for CBufFlat ctor when serializing contact links
+const TInt KBufGranularity = 64;
+
+// default security policy (use LocalServices cap) for contexts
+_LIT_SECURITY_POLICY_C1( KContextSecurity, ECapabilityLocalServices );
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::NewL
+// -----------------------------------------------------------------------------
+//
+CHgContextUtilityImpl* CHgContextUtilityImpl::NewL()
+ {
+ CHgContextUtilityImpl* self = NewLC();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::NewLC
+// -----------------------------------------------------------------------------
+//
+CHgContextUtilityImpl* CHgContextUtilityImpl::NewLC()
+ {
+ CHgContextUtilityImpl* self = new ( ELeave ) CHgContextUtilityImpl;
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::CHgContextUtilityImpl
+// -----------------------------------------------------------------------------
+//
+CHgContextUtilityImpl::CHgContextUtilityImpl()
+ : CTimer( CActive::EPriorityStandard )
+ {
+ CActiveScheduler::Add( this );
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::ConstructL()
+ {
+ CTimer::ConstructL();
+
+ iEnv = CCoeEnv::Static(); // may be NULL
+
+ // Do not create iCFClient here as cf server may not be available yet
+ // if we are early in the boot phase.
+
+ // set defaults
+ RePublishWhenFgL( EFalse );
+ AllowPublishFromBackground( EFalse );
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::~CHgContextUtilityImpl
+// -----------------------------------------------------------------------------
+//
+CHgContextUtilityImpl::~CHgContextUtilityImpl()
+ {
+ Cancel();
+ delete iPendingContextType;
+ delete iPendingContextData;
+ delete iPendingContextDataArray;
+ delete iCFClient;
+ delete iLastContextType;
+ delete iLastContextData;
+ if ( iFgWatchEnabled && iEnv )
+ {
+ iEnv->RemoveForegroundObserver( *this );
+ }
+
+ iMusicContextInfo.ResetAndDestroy();
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::CFReady
+// -----------------------------------------------------------------------------
+//
+TBool CHgContextUtilityImpl::CFReady()
+ {
+ if ( !iCFClient )
+ {
+ TRAPD( err, iCFClient = CCFClient::NewL( *this ) );
+ if ( err != KErrNone )
+ {
+ RDebug::Printf( "[hgctxutil] cfw not ready" );
+ return EFalse;
+ }
+ }
+ return ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishContextL
+// All other non-static versions of this function will fall back to this one.
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishContextL( const TDesC& aContextType,
+ const TDesC& aContextData )
+ {
+ RDebug::Print( _L("[hgctxutil] PublishContextL [%S] [%S]"),
+ &aContextType, &aContextData );
+ // create cf client instance if not yet done
+ // and check foreground status if needed
+ if ( CFReady() && AllowedToPublish() )
+ {
+ // call static version with our cf client instance
+ PublishContextL( *iCFClient, aContextType, aContextData );
+ }
+ // store type and value for later use
+ // (even when cfserver is not available yet, the data may still be
+ // used later when the app comes to foreground, for example)
+ if ( iLastContextType != &aContextType )
+ {
+ delete iLastContextType; iLastContextType = 0;
+ iLastContextType = aContextType.AllocL();
+ }
+ if ( iLastContextData != &aContextData )
+ {
+ delete iLastContextData; iLastContextData = 0;
+ iLastContextData = aContextData.AllocL();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// AppendCharL
+// Appends a char to aDst, calls ReAllocL when needed, assumes that aDst
+// is also on cleanupstack (at top position) so it updates that pointer too.
+// -----------------------------------------------------------------------------
+//
+LOCAL_C void AppendCharL( HBufC*& aDst, TChar aChar )
+ {
+ TPtr des( aDst->Des() );
+ if ( des.Length() == des.MaxLength() )
+ {
+ HBufC* oldDst = aDst;
+ aDst = aDst->ReAllocL( des.MaxLength() * 2 );
+ CleanupStack::Pop( oldDst ); // pop the old pointer
+ CleanupStack::PushL( aDst ); // and push the new (possibly different) one
+ des.Set( aDst->Des() );
+ }
+ des.Append( aChar );
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::BuildCombinedStringL
+// -----------------------------------------------------------------------------
+//
+HBufC* CHgContextUtilityImpl::BuildCombinedStringL(
+ const MDesCArray& aArray )
+ {
+ TInt arrayCount = aArray.MdcaCount();
+ if ( arrayCount >= 2 )
+ {
+ // Rules:
+ // 1. escape all separator chars in the input with a preceeding \
+ // 2. escape all \ chars in the input with \\
+ // 3. take only the first KMaxEntriesInMulti elements from the array
+ // 4. append a separator also after last entry
+ // 5. prepend two separators to the combined string
+ TInt processedEntryCount = Min( arrayCount, KMaxEntriesInMulti );
+ // calculate a big enough size so we can avoid ReAllocL calls later
+ TInt sz = 0;
+ for ( TInt i = 0; i < processedEntryCount; ++i )
+ {
+ sz += aArray.MdcaPoint( i ).Length() + 1;
+ }
+ sz += 2; // for the magic prefix
+ HBufC* value = HBufC::NewLC( sz );
+ AppendCharL( value, KMultiSepChar );
+ AppendCharL( value, KMultiSepChar );
+ for ( TInt i = 0; i < processedEntryCount; ++i )
+ {
+ TPtrC entry( aArray.MdcaPoint( i ) );
+ // append, also do the escaping
+ for ( TInt j = 0, je = entry.Length(); j != je; ++j )
+ {
+ TChar c = entry[j];
+ if ( c == KMultiSepChar || c == '\\' )
+ {
+ AppendCharL( value, '\\' );
+ }
+ AppendCharL( value, c );
+ }
+ AppendCharL( value, KMultiSepChar );
+ }
+ CleanupStack::Pop( value );
+ return value;
+ }
+ return 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::SplitCombinedStringL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::SplitCombinedStringL(
+ const TDesC& aString, CDesCArray& aArray )
+ {
+ TInt inputLength = aString.Length();
+ TBool isMulti = inputLength > 2
+ && aString[0] == KMultiSepChar && aString[1] == KMultiSepChar;
+ if ( isMulti )
+ {
+ // allocate a work buffer that is big enough for sure
+ HBufC* buf = HBufC::NewLC( inputLength );
+ TPtr des( buf->Des() );
+ TBool esc = EFalse;
+ // go through the string, find entries, and add them to output array
+ for ( TInt i = 2; i < inputLength; ++i ) // start from 2 because of the magic prefix
+ {
+ TChar c = aString[i];
+ if ( c == '\\' && !esc )
+ {
+ esc = ETrue;
+ }
+ else if ( c == KMultiSepChar && !esc )
+ {
+ // found separator: append to output array, clear buffer, and continue
+ aArray.AppendL( des );
+ des.Zero();
+ }
+ else
+ {
+ esc = EFalse;
+ des.Append( c );
+ }
+ }
+ CleanupStack::PopAndDestroy( buf );
+ }
+ else
+ {
+ // not a combined string: append to array as it is
+ aArray.AppendL( aString );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishContextL( const TDesC& aContextType,
+ const MDesCArray& aContextData )
+ {
+ TInt entryCount = aContextData.MdcaCount();
+ // do nothing if array is empty
+ if ( !entryCount )
+ {
+ return;
+ }
+ // nothing special when having only 1 item
+ if ( entryCount == 1 )
+ {
+ PublishContextL( aContextType, aContextData.MdcaPoint( 0 ) );
+ return;
+ }
+ // at least two items: create the special combined string
+ HBufC* value = BuildCombinedStringL( aContextData );
+ CleanupStack::PushL( value );
+ // publish the combined string
+ PublishContextL( aContextType, *value );
+ CleanupStack::PopAndDestroy( value );
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishContextL
+// This is the version of the function where the real work is performed.
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishContextL( CCFClient& aCFClient,
+ const TDesC& aContextType, const TDesC& aContextData )
+ {
+ CCFContextObject* context = CCFContextObject::NewLC();
+ context->SetSourceL( KHgCFSource );
+ context->SetTypeL( aContextType );
+ context->SetValueL( aContextData );
+ TInt err = aCFClient.PublishContext( *context );
+ if ( err == KErrNotFound )
+ {
+ User::LeaveIfError( aCFClient.DefineContext( KHgCFSource,
+ aContextType, KContextSecurity ) );
+ err = aCFClient.PublishContext( *context );
+ if ( err != KErrArgument ) // ignore -6 which comes e.g. when trying to publish an empty value
+ {
+ User::LeaveIfError( err );
+ }
+ }
+ else if ( err != KErrArgument )
+ {
+ User::LeaveIfError( err );
+ }
+ CleanupStack::PopAndDestroy( context );
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::GetContextL
+// -----------------------------------------------------------------------------
+//
+HBufC* CHgContextUtilityImpl::GetContextL( const TDesC& aContextSource,
+ const TDesC& aContextType )
+ {
+ HBufC* ret = 0;
+ if ( CFReady() )
+ {
+ CCFContextQuery* query = CCFContextQuery::NewLC();
+ query->SetSourceL( aContextSource );
+ query->SetTypeL( aContextType );
+ RContextObjectArray result;
+ TInt err = iCFClient->RequestContext( *query, result );
+ if ( err == KErrNone && result.Count() )
+ {
+ ret = result[0]->Value().Alloc();
+ }
+ result.ResetAndDestroy();
+ CleanupStack::PopAndDestroy( query );
+ }
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::GetContextL
+// -----------------------------------------------------------------------------
+//
+HBufC* CHgContextUtilityImpl::GetContextL( const TDesC& aContextType )
+ {
+ return GetContextL( KHgCFSource, aContextType );
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishContextDelayedL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishContextDelayedL( const TDesC& aContextType,
+ const TDesC& aContextData, TTimeIntervalMicroSeconds32 aDelay )
+ {
+ Cancel();
+ delete iPendingContextType; iPendingContextType = 0;
+ iPendingContextType = aContextType.AllocL();
+ delete iPendingContextData; iPendingContextData = 0;
+ iPendingContextData = aContextData.AllocL();
+ delete iPendingContextDataArray; iPendingContextDataArray = 0;
+ After( aDelay );
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishContextDelayedL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishContextDelayedL( const TDesC& aContextType,
+ const MDesCArray& aContextData, TTimeIntervalMicroSeconds32 aDelay )
+ {
+ Cancel();
+ delete iPendingContextType; iPendingContextType = 0;
+ iPendingContextType = aContextType.AllocL();
+ delete iPendingContextData; iPendingContextData = 0;
+ if ( iPendingContextDataArray )
+ {
+ iPendingContextDataArray->Reset();
+ }
+ else
+ {
+ iPendingContextDataArray = new ( ELeave ) CDesC16ArrayFlat( KArrayGranularity );
+ }
+ for ( TInt i = 0, ie = aContextData.MdcaCount(); i != ie; ++i )
+ {
+ iPendingContextDataArray->AppendL( aContextData.MdcaPoint( i ) );
+ }
+ After( aDelay );
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::RunL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::RunL()
+ {
+ if ( iPendingContextType )
+ {
+ if ( iPendingContextData )
+ {
+ PublishContextL( *iPendingContextType, *iPendingContextData );
+ }
+ else if ( iPendingContextDataArray )
+ {
+ PublishContextL( *iPendingContextType, *iPendingContextDataArray );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::RunError
+// -----------------------------------------------------------------------------
+//
+TInt CHgContextUtilityImpl::RunError( TInt /*aError*/ )
+ {
+ return KErrNone;
+ }
+
+// empty implementations for cfw
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::ContextIndicationL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::ContextIndicationL(
+ const CCFContextIndication& /*aChangedContext*/ )
+ {
+ // empty
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::ActionIndicationL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::ActionIndicationL(
+ const CCFActionIndication& /*aActionToExecute*/ )
+ {
+ // empty
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::HandleContextFrameworkError
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::HandleContextFrameworkError( TCFError /*aError*/,
+ const TDesC& /*aSource*/,
+ const TDesC& /*aType*/ )
+ {
+ // empty
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::Extension
+// -----------------------------------------------------------------------------
+//
+TAny* CHgContextUtilityImpl::Extension( const TUid& /*aExtensionUid*/ ) const
+ {
+ return 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::MakeLinkPublishableLC
+// -----------------------------------------------------------------------------
+//
+HBufC* CHgContextUtilityImpl::MakeLinkPublishableLC(
+ const MVPbkContactLink& aLink )
+ {
+ HBufC* ret = 0;
+ // serialize the link and place it into a 16-bit descriptor
+ // prefixed with one special mark character
+ const MVPbkStreamable* strm = aLink.Streamable();
+ User::LeaveIfNull(strm);
+ CBufFlat* buf = CBufFlat::NewL( KBufGranularity );
+ CleanupStack::PushL( buf );
+ RBufWriteStream ws;
+ CleanupClosePushL( ws );
+ ws.Open( *buf );
+ strm->ExternalizeL( ws );
+ CleanupStack::PopAndDestroy( &ws );
+ TPtr8 p( buf->Ptr( 0 ) );
+ ret = HBufC::NewLC( p.Length() + 1 );
+ TPtr des( ret->Des() );
+ des.Copy( p );
+ _LIT( KTemp, " " );
+ des.Insert( 0, KTemp );
+ des[0] = KHgCFValueLinkMarker; // codescanner::accessArrayElementWithoutCheck2
+ CleanupStack::Pop( ret );
+ CleanupStack::PopAndDestroy( buf );
+ CleanupStack::PushL( ret );
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishContactContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishContactContextL(
+ const MVPbkStoreContact& aContact,
+ const TTimeIntervalMicroSeconds32& aDelay )
+ {
+ MVPbkContactLink* link = aContact.CreateLinkLC();
+ if ( link )
+ {
+ HBufC* pubstr = MakeLinkPublishableLC( *link );
+ PublishContactContextL( *pubstr, aDelay );
+ CleanupStack::PopAndDestroy( pubstr );
+ }
+ CleanupStack::PopAndDestroy( );//link
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishContactContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishContactContextL(
+ const MVPbkContactLink& aContactLink,
+ const TTimeIntervalMicroSeconds32& aDelay )
+ {
+ HBufC* pubstr = MakeLinkPublishableLC( aContactLink );
+ PublishContactContextL( *pubstr, aDelay );
+ CleanupStack::PopAndDestroy( pubstr );
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishContactContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishContactContextL(
+ const TDesC& aContactName,
+ const TTimeIntervalMicroSeconds32& aDelay )
+ {
+ if ( !aDelay.Int() )
+ {
+ PublishContextL( KHgCFTypeContact, aContactName );
+ }
+ else
+ {
+ PublishContextDelayedL( KHgCFTypeContact, aContactName, aDelay );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishContactContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishContactContextL(
+ const RPointerArray<MVPbkStoreContact>& aContacts,
+ const TTimeIntervalMicroSeconds32& aDelay )
+ {
+ CDesCArray* arr = new ( ELeave ) CDesCArrayFlat( KArrayGranularity );
+ CleanupStack::PushL( arr );
+ for ( TInt i = 0, ie = aContacts.Count(); i != ie; ++i )
+ {
+ MVPbkContactLink* link = aContacts[i]->CreateLinkLC();
+ if ( link )
+ {
+ HBufC* pubstr = MakeLinkPublishableLC( *link );
+ arr->AppendL( *pubstr );
+ CleanupStack::PopAndDestroy( pubstr );
+ }
+ CleanupStack::PopAndDestroy( );//link
+ }
+ PublishContactContextL( *arr, aDelay );
+ CleanupStack::PopAndDestroy( arr );
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishContactContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishContactContextL(
+ const CVPbkContactLinkArray& aContactLinks,
+ const TTimeIntervalMicroSeconds32& aDelay )
+ {
+ CDesCArray* arr = new ( ELeave ) CDesCArrayFlat( KArrayGranularity );
+ CleanupStack::PushL( arr );
+ for ( TInt i = 0, ie = aContactLinks.Count(); i != ie; ++i )
+ {
+ HBufC* pubstr = MakeLinkPublishableLC( aContactLinks.At( i ) );
+ arr->AppendL( *pubstr );
+ CleanupStack::PopAndDestroy( pubstr );
+ }
+ PublishContactContextL( *arr, aDelay );
+ CleanupStack::PopAndDestroy( arr );
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishContactContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishContactContextL(
+ const MDesCArray& aContactNames,
+ const TTimeIntervalMicroSeconds32& aDelay )
+ {
+ if ( !aDelay.Int() )
+ {
+ PublishContextL( KHgCFTypeContact, aContactNames );
+ }
+ else
+ {
+ PublishContextDelayedL( KHgCFTypeContact, aContactNames, aDelay );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishTextContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishTextContextL( const TDesC& aText,
+ const TTimeIntervalMicroSeconds32& aDelay )
+ {
+ if ( !aDelay.Int() )
+ {
+ PublishContextL( KHgCFTypeText, aText );
+ }
+ else
+ {
+ PublishContextDelayedL( KHgCFTypeText, aText, aDelay );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishUrlContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishUrlContextL( const TDesC& aUrl,
+ const TTimeIntervalMicroSeconds32& aDelay )
+ {
+ if ( !aDelay.Int() )
+ {
+ PublishContextL( KHgCFTypeUrl, aUrl );
+ }
+ else
+ {
+ PublishContextDelayedL( KHgCFTypeUrl, aUrl, aDelay );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishTimeContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishTimeContextL( const TTime& aTime,
+ const TTimeIntervalMicroSeconds32& aDelay )
+ {
+ // YYYYMMDD:HHMMSS.MMMMMM
+ const TInt KDateTimeLength = 22;
+ const TInt KYearLength = 4;
+ const TInt KMonthLength = 2;
+ const TInt KDayLength = 2;
+ _LIT( KTimeZero, ":010101.000000");
+
+ TDateTime dt = aTime.DateTime();
+ TBuf<KDateTimeLength> buf;
+ buf.AppendNumFixedWidth( dt.Year(), EDecimal, KYearLength );
+ buf.AppendNumFixedWidth( dt.Month(), EDecimal, KMonthLength );
+ buf.AppendNumFixedWidth( dt.Day(), EDecimal, KDayLength );
+ buf.Append( KTimeZero );
+ if ( !aDelay.Int() )
+ {
+ PublishContextL( KHgCFTypeActiveDate, buf );
+ }
+ else
+ {
+ PublishContextDelayedL( KHgCFTypeActiveDate, buf, aDelay );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishPhotoContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishPhotoContextL(
+ const TDesC& aFilename,
+ const TTimeIntervalMicroSeconds32& aDelay )
+ {
+ if ( !aDelay.Int() )
+ {
+ PublishContextL( KHgCFTypePhoto, aFilename );
+ }
+ else
+ {
+ PublishContextDelayedL( KHgCFTypePhoto, aFilename, aDelay );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishPhotoContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishPhotoContextL(
+ TItemId aMdeItemId,
+ CMdESession& aMdeSession,
+ const TTimeIntervalMicroSeconds32& aDelay )
+ {
+ CMdEObject* obj = aMdeSession.GetObjectL( aMdeItemId );
+ if ( obj )
+ {
+ CleanupStack::PushL( obj );
+ PublishPhotoContextL( obj->Uri(), aDelay );
+ CleanupStack::PopAndDestroy( obj );
+ }
+ else
+ {
+ User::Leave( KErrNotFound );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishTvContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishTvContextL( const TDesC& aChannelName,
+ const TDesC& aProgramName, const TDesC& aProgramDescription,
+ const TDesC& aGenre )
+ {
+ TPtrC channelName( aChannelName.Length() ? aChannelName
+ : KHgCFValueUnknownInfo );
+ TPtrC programName( aProgramName.Length() ? aProgramName
+ : KHgCFValueUnknownInfo );
+ TPtrC programDesc( aProgramDescription.Length() ? aProgramDescription
+ : KHgCFValueUnknownInfo );
+ TPtrC programGenre( aGenre.Length() ? aGenre : KHgCFValueUnknownInfo );
+
+ // Publish description/genre first because it is unlikely to have those
+ // in rules so their content will be available for sure when an action
+ // is triggered.
+ PublishContextL( KHgCFTypeTvProgramDesc, programDesc );
+ PublishContextL( KHgCFTypeTvProgramGenre, programGenre );
+ PublishContextL( KHgCFTypeTvChannelName, channelName );
+ PublishContextL( KHgCFTypeTvProgramName, programName );
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishServiceIdL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishServiceIdL( const TDesC& aServiceId,
+ const TDesC& aAccountId,
+ const TTimeIntervalMicroSeconds32& aDelay )
+ {
+ HBufC* combinedIdBuf = HBufC::NewLC( aServiceId.Length()
+ + aAccountId.Length() + 1 );
+ TPtr combinedId( combinedIdBuf->Des() );
+ _LIT( KCombinedFormat, "%S:%S" );
+ combinedId.Format( KCombinedFormat, &aServiceId, &aAccountId );
+ PublishContactContextL( combinedId, aDelay );
+ CleanupStack::PopAndDestroy( combinedIdBuf );
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::RePublishWhenFgL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::RePublishWhenFgL( TBool aEnable )
+ {
+ if ( iEnv )
+ {
+ if ( iFgWatchEnabled )
+ {
+ iEnv->RemoveForegroundObserver( *this );
+ }
+ iFgWatchEnabled = aEnable;
+ if ( iFgWatchEnabled )
+ {
+ iEnv->AddForegroundObserverL( *this );
+ }
+ }
+ }
+
+// callbacks from CCoeEnv
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::HandleGainingForeground
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::HandleGainingForeground()
+ {
+ if ( iLastContextType && iLastContextData )
+ {
+ TRAP_IGNORE( PublishContextL( *iLastContextType, *iLastContextData ) );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::HandleLosingForeground
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::HandleLosingForeground()
+ {
+ // nothing to do here
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::IsForeground
+// -----------------------------------------------------------------------------
+//
+TBool CHgContextUtilityImpl::IsForeground()
+ {
+ if ( iEnv )
+ {
+ TInt rootWgId = iEnv->RootWin().WindowGroupId();
+ TInt focusWgId = iEnv->WsSession().GetFocusWindowGroup();
+ return rootWgId == focusWgId;
+ }
+ else
+ {
+ return ETrue;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::AllowedToPublish
+// -----------------------------------------------------------------------------
+//
+TBool CHgContextUtilityImpl::AllowedToPublish()
+ {
+ TBool result = !iEnv || iAllowPublishFromBackground || IsForeground();
+ RDebug::Printf( "[hgctxutil] AllowedToPublish = %d", result );
+ return result;
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::AllowPublishFromBackground
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::AllowPublishFromBackground( TBool aAllow )
+ {
+ iAllowPublishFromBackground = aAllow;
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::AddMusicContextInfoL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::AddMusicContextInfoL(
+ const TDesC& aKey, const TDesC& aData )
+ {
+ // Key needs to be provided and also it shouldn't exist in the table.
+ // Latter case is simple safe measure, as RPtrHasMap won't delete existing
+ // objects in InsertL, so adding same key twice would cause memory leak.
+ // The use case of adding same key twice is not 'real world' case, so
+ // this method can simply leave, when same key is offered again.
+ __ASSERT_ALWAYS( aKey.Length(), User::Leave( KErrNotFound ) );
+ __ASSERT_ALWAYS(
+ !iMusicContextInfo.Find( aKey ), User::Leave( KErrAlreadyExists ) );
+
+ // Hash table needs pointers and it should own the pointers, so allocate
+ // key and data, and add them to table. In case the data is empty, add
+ // unknown information, since some data needs to be in the action field.
+ HBufC* key = aKey.AllocLC();
+ HBufC* data = aData.Length() ?
+ aData.AllocLC() : KHgCFValueUnknownInfo().AllocLC();
+ iMusicContextInfo.InsertL( key, data );
+ CleanupStack::Pop( 2, key );
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishMusicContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishMusicContextL(
+ const TTimeIntervalMicroSeconds32& aDelay )
+ {
+ // If nothing has been done, just leave. No point of publishing entirely
+ // empty music context.
+ __ASSERT_ALWAYS( iMusicContextInfo.Count(), User::Leave( KErrNotReady ) );
+
+ // Before publishing anything, make sure all keys contain at least some
+ // data.
+ VerifyAndPublishMusicContextL( KHgCFTypeMusicState, aDelay );
+ VerifyAndPublishMusicContextL( KHgCFTypeMusicArtist, aDelay );
+ VerifyAndPublishMusicContextL( KHgCFTypeMusicTitle, aDelay );
+ VerifyAndPublishMusicContextL( KHgCFTypeMusicAlbum, aDelay );
+ VerifyAndPublishMusicContextL( KHgCFTypeMusicAlbumArt, aDelay );
+ VerifyAndPublishMusicContextL( KHgCFTypeMusicUri, aDelay );
+ VerifyAndPublishMusicContextL( KHgCFTypeMusicGenre, aDelay );
+ VerifyAndPublishMusicContextL( KHgCFTypeMusicType, aDelay );
+
+ // Clear all data from hash table, so new music context can be published.
+ iMusicContextInfo.ResetAndDestroy();
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::VerifyAndPublishMusicContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::VerifyAndPublishMusicContextL(
+ const TDesC& aKey,
+ const TTimeIntervalMicroSeconds32& aDelay )
+ {
+ TDesC* data = iMusicContextInfo.Find( aKey );
+ if ( !data )
+ {
+ // Key didn't contain any data, just create the key with empty info.
+ AddMusicContextInfoL( aKey, KNullDesC );
+ data = iMusicContextInfo.Find( aKey );
+ }
+
+ PublishContextL( aKey, *data, aDelay );
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishContextL(
+ const TDesC & aContextType,
+ const TDesC & aContextData,
+ const TTimeIntervalMicroSeconds32& aDelay )
+ {
+ if ( !aDelay.Int() )
+ {
+ PublishContextL( aContextType, aContextData );
+ }
+ else
+ {
+ PublishContextDelayedL( aContextType, aContextData, aDelay );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHgContextUtilityImpl::PublishRadioContextL
+// -----------------------------------------------------------------------------
+//
+void CHgContextUtilityImpl::PublishRadioContextL(
+ const TDesC& aRadioName,
+ const TDesC& aRadioUrl,
+ const TDesC& aRadioFrequency,
+ const TDesC& aRadioRDSPI )
+ {
+ TPtrC radioName( aRadioName.Length() ? aRadioName
+ : KHgCFValueUnknownInfo );
+ TPtrC radioUrl( aRadioUrl.Length() ? aRadioUrl
+ : KHgCFValueUnknownInfo );
+ TPtrC radioFrequency( aRadioFrequency.Length() ? aRadioFrequency
+ : KHgCFValueUnknownInfo );
+ TPtrC radioRDSPI( aRadioRDSPI.Length() ? aRadioRDSPI
+ : KHgCFValueUnknownInfo );
+
+ PublishContextL( KHgCFTypeMusicRadioRDSPI, radioRDSPI );
+ PublishContextL( KHgCFTypeMusicRadioFrequency, radioFrequency );
+ PublishContextL( KHgCFTypeMusicRadioUrl, radioUrl );
+ PublishContextL( KHgCFTypeMusicRadioName, radioName );
+ }
+
+// end of file