diff -r 000000000000 -r 2e3d3ce01487 contextframework/cfwplugins/ApplicationStateSourcePlugIn/src/ApplicationStateSourcePlugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contextframework/cfwplugins/ApplicationStateSourcePlugIn/src/ApplicationStateSourcePlugin.cpp Tue Feb 02 10:12:00 2010 +0200 @@ -0,0 +1,747 @@ +/* +* Copyright (c) 2002-2009 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: ?Description +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#endif + +#include "ApplicationStateSourcePlugin.h" +#include "ApplicationStateSourceContextDef.h" +#include "ContextFrameworkPrivateCRKeys.h" +#include "trace.h" + +// CONSTANTS + +#ifdef _DEBUG +// Panic codes +enum TPanicCode + { + EInvalidUid, + EInvalidAttribute + }; +#endif + +_LIT( KDefaultApplicationName, "DefaultAppName" ); +_LIT( KDefaultViewName, "DefaultViewName" ); +_LIT( KAttributeAppUid, "AppUid" ); +_LIT( KAttributeAppName, "AppName" ); +_LIT( KTagView, "View" ); +_LIT( KAttributeUid, "Uid" ); +_LIT( KAttributeName, "Name" ); + +const TUint KLimit = 0xFFFFFFFF; + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CApplicationStateSourcePlugIn::CApplicationStateSourcePlugIn +// C++ default constructor can NOT contain any code, that might leave. +// ----------------------------------------------------------------------------- +// +CApplicationStateSourcePlugIn::CApplicationStateSourcePlugIn( TContextSourceInitParams* aParams ): + CCFContextSourcePlugIn( aParams ), + iDefStateSetManyTimes( 0 ) + { + FUNC_LOG; + } + +// ----------------------------------------------------------------------------- +// CApplicationStateSourcePlugIn::ConstructL +// Symbian second-phase constructor that may leave. +// ----------------------------------------------------------------------------- +// +void CApplicationStateSourcePlugIn::ConstructL() + { + FUNC_LOG; + + iDefaultAppName = KApplicationStateDefaultValue().AllocL(); + iDefaultViewName = KApplicationStateDefaultValue().AllocL(); + iContext = CCFContextObject::NewL(); + } + +// ----------------------------------------------------------------------------- +// CApplicationStateSourcePlugIn::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CApplicationStateSourcePlugIn* CApplicationStateSourcePlugIn::NewL( + TContextSourceInitParams* aParams ) + { + FUNC_LOG; + + CApplicationStateSourcePlugIn* self = CApplicationStateSourcePlugIn::NewLC( + aParams ); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CApplicationStateSourcePlugIn::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CApplicationStateSourcePlugIn* CApplicationStateSourcePlugIn::NewLC( + TContextSourceInitParams* aParams ) + { + FUNC_LOG; + + CApplicationStateSourcePlugIn* self = new( ELeave ) CApplicationStateSourcePlugIn( + aParams ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + +// Destructor +CApplicationStateSourcePlugIn::~CApplicationStateSourcePlugIn() + { + FUNC_LOG; + + if( iCRAppOrientationListener ) + { + iCRAppOrientationListener->StopListening(); + delete iCRAppOrientationListener; + } + iUidOrientationList.Close(); + delete iCRAppOrientation; + iApplicationSettings.ResetAndDestroy(); + delete iSettings; + delete iVws; + delete iDefaultViewName; + delete iDefaultAppName; + delete iApplDefaultState; + delete iContext; + } + +// ----------------------------------------------------------------------------- +// CApplicationStateSourcePlugIn::HandleSettingL +// ----------------------------------------------------------------------------- +// +void CApplicationStateSourcePlugIn::HandleSettingL( + CCFContextSourceSettingArray* aSettingList ) + { + FUNC_LOG; + + // Take ownership from settings + iSettings = aSettingList; + } + +// ----------------------------------------------------------------------------- +// CApplicationStateSourcePlugIn::DefineContextsL +// ----------------------------------------------------------------------------- +// +void CApplicationStateSourcePlugIn::DefineContextsL() + { + FUNC_LOG; + + // Define contexts here + _LIT_SECURITY_POLICY_C2( + appStatePolicy, ECapabilitySwEvent, ECapabilityUserEnvironment ); + + TInt err = iCF.DefineContext( KApplicationStateSource, + KApplicationStateForegroundApplicationType, + appStatePolicy ); + User::LeaveIfError( err ); + + err = iCF.DefineContext( KApplicationStateSource, + KApplicationStateForegroundApplicationViewType, + appStatePolicy ); + User::LeaveIfError( err ); + + err = iCF.DefineContext( KApplicationStateSource, + KApplicationStateBackgroundApplicationType, + appStatePolicy ); + User::LeaveIfError( err ); + + err = iCF.DefineContext( KApplicationStateSource, + KFgApplicationOrientation, + KFgApplicationOrientationSec ); + User::LeaveIfError( err ); + } + +// ----------------------------------------------------------------------------- +// CApplicationStateSourcePlugIn::InitializeL +// ----------------------------------------------------------------------------- +// +void CApplicationStateSourcePlugIn::InitializeL() + { + FUNC_LOG; + + iContext->SetSourceL( KApplicationStateSource ); + + // Get default app orientation + CRepository* cenRep = CRepository::NewL( KCRUidCFApplDefaultState ); + TInt err = cenRep->Get( KApplDefaultState, iDefaultFgAppOrientation ); + if( err != KErrNone ) + { + ERROR( err, "Failed to get default fg app orientation" ); + iDefaultFgAppOrientation = 0; + } + delete cenRep; + cenRep = NULL; + + // Create KCRUidDefaultAppOrientation repository for default app orientation + iCRAppOrientation = CRepository::NewL( KCRUidDefaultAppOrientation ); + + // Create KCRUidDefaultAppOrientation repository listener + iCRAppOrientationListener = CCenRepNotifyHandler::NewL( + *this, *iCRAppOrientation ); + iCRAppOrientationListener->StartListeningL(); + + if( iSettings ) + { + InitializeApplicationsFromXMLL(); + InitializeFgApplicationL(); + + // Free memory allocated for settings since we don't need them anymore + delete iSettings; + iSettings = NULL; + } + + iVws = CVwsSessionWrapper::NewL( *this ); + iVws->NotifyNextActivation(); + } + +// ----------------------------------------------------------------------------- +// CApplicationStateSourcePlugIn::InitializeApplicationsFromXMLL +// ----------------------------------------------------------------------------- +// +void CApplicationStateSourcePlugIn::InitializeApplicationsFromXMLL() + { + FUNC_LOG; + + for( TInt i = 0; i < iSettings->Count(); ++i ) + { + // Check attributes + TBool defaultValueDefinitions = EFalse; + TPtrC appUid( KNullDesC ); + TPtrC appName( KNullDesC ); + const RKeyValueArray& attributes = iSettings->Item( i ).Attributes(); + + // Check application and view names (also default values) + for( TInt j = 0; j < attributes.Count(); ++j ) + { + TPtrC key( attributes[ j ]->Key() ); + TPtrC value( attributes[ j ]->Value() ); + + if( key.CompareF( KAttributeAppUid ) == KErrNone ) + { + appUid.Set( value ); + } + else if( key.CompareF( KAttributeAppName ) == KErrNone ) + { + appName.Set( value ); + } + else if( key.CompareF( KDefaultApplicationName ) == KErrNone ) + { + delete iDefaultAppName; + iDefaultAppName = NULL; + iDefaultAppName = value.AllocL(); + defaultValueDefinitions = ETrue; + } + else if( key.CompareF( KDefaultViewName ) == KErrNone ) + { + delete iDefaultViewName; + iDefaultViewName = NULL; + iDefaultViewName = value.AllocL(); + defaultValueDefinitions = ETrue; + } + } + + if ( defaultValueDefinitions ) + { + continue; // Default value definitions contain only attributes. + } + + if ( appUid.Length() == 0 || appName.Length() == 0 ) + { + ERROR_GEN( "Either AppUid or AppName tag (or both) not found, skipping" ); + continue; // Skip this definition. + } + + TUint32 uid = 0; + TInt err = ConvertToHex( appUid, uid ); + if( err != KErrNone ) + { + ERROR_1( err, "Invalid uid [%S] for an application, skipping", &appUid ); + continue; // Skip this definition. + } + + // below: CLEANUP<< appStateSettings + CCFApplicationStateSettings* appStateSettings + = CCFApplicationStateSettings::NewLC( TUid::Uid( uid ), appName ); + + // Check parameters + const RSettingParameterArray& parameters = iSettings->Item( i ).Parameters(); + for( TInt j = 0; j < parameters.Count(); ++j ) + { + if ( parameters[ j ]->Name() != KTagView ) + { + continue; // At the moment, handle only view tags + } + + TPtrC viewUid( KNullDesC ); + TPtrC viewName( KNullDesC ); + const RKeyValueArray& paramAttr = parameters[ j ]->Attributes(); + for( TInt k = 0; k < paramAttr.Count(); ++k ) + { + TPtrC key( paramAttr[ k ]->Key() ); + TPtrC value( paramAttr[ k ]->Value() ); + + // Check view uid + if( key.CompareF( KAttributeUid ) == KErrNone ) + { + viewUid.Set( value ); + } + // Check view name + else if( key.CompareF( KAttributeName ) == KErrNone ) + { + viewName.Set( value ); + } + } + + if ( viewUid.Length() == 0 || viewName.Length() == 0 ) + { + ERROR_GEN( "Either View's Uid or Name tag (or both) not found, skipping" ); + continue; // Skip this definition. + } + + uid = 0; + TInt err = ConvertToHex( viewUid, uid ); + if( err != KErrNone ) + { + ERROR_1( err, "Invalid view uid [%S], skipping", &viewUid ); + continue; // Skip this definition. + } + + // below: CLEANUP<< viewUidName + CCFUidNamePair* viewUidName + = CCFUidNamePair::NewLC( TUid::Uid( uid ), viewName ); + appStateSettings->AddViewSettingsL( viewUidName ); + CleanupStack::Pop( viewUidName ); // CLEANUP>> viewUidName + } + + iApplicationSettings.AppendL( appStateSettings ); + CleanupStack::Pop( appStateSettings ); // CLEANUP>> appStateSettings + } + } + +// ----------------------------------------------------------------------------- +// CApplicationStateSourcePlugIn::HandleViewEventL +// Maps view activations to contexts. +// ----------------------------------------------------------------------------- +// +void CApplicationStateSourcePlugIn::HandleViewEventL( + const TVwsViewEvent& aEvent ) + { + FUNC_LOG; + + // Renew listening + iVws->NotifyNextActivation(); + + // Handle the view server event + DoHandleViewEventL( aEvent ); + + // Log event members! + INFO_1( "HandleViewEventL: eventType: [%d]", aEvent.iEventType ); + + INFO_2( "HandleViewEventL: viewOne [appUid:%S] [viewUid%S]", + &(const TDesC&)aEvent.iViewOneId.iAppUid.Name(), + &(const TDesC&)aEvent.iViewOneId.iViewUid.Name() ); + + INFO_2( "HandleViewEventL: viewTwo [appUid:%S] [viewUid%S]", + &(const TDesC&)aEvent.iViewTwoId.iAppUid.Name(), + &(const TDesC&)aEvent.iViewTwoId.iViewUid.Name() ); + } + +//------------------------------------------------------------------------------ +// CApplicationStateSourcePlugIn::HandleNotifyGeneric +//------------------------------------------------------------------------------ +// +void CApplicationStateSourcePlugIn::HandleNotifyGeneric( TUint32 aId ) + { + FUNC_LOG; + + // Get the new value from cenrep + TInt val = 0; + TInt err = iCRAppOrientation->Get( aId, val ); + if( err == KErrNone ) + { + // New value found, check if the element is found from cache + TInt index = FindByUid( TUid::Uid( aId ) ); + if( index != KErrNotFound ) + { + // Update cache element + TUidOrientationPair& pair = iUidOrientationList[index]; + pair.iOrientation = val; + INFO_2( "Updated cache uid: [0x%x] to orientation: [%d]", pair.iUid.iUid, val ); + } + else + { + // Add new cache element + TUidOrientationPair pair( TUid::Uid( aId ), val ); + err = iUidOrientationList.Append( pair ); + if( err == KErrNone ) + { + INFO_2( "Added cache uid: [0x%x], orientation: [%d]", pair.iUid.iUid, val ); + } + else + { + ERROR_1( err, "Failed to add cache uid: [0x%x]", pair.iUid.iUid ); + } + } + } + else + { + ERROR_1( err, "Failed to get new value from CR key: [0x%x]", aId ); + } + } + +// ----------------------------------------------------------------------------- +// CApplicationStateSourcePlugIn::DoHandleViewEventL +// Maps view activations to contexts. +// ----------------------------------------------------------------------------- +// +void CApplicationStateSourcePlugIn::DoHandleViewEventL( + const TVwsViewEvent& aEvent ) + { + FUNC_LOG; + + TPtrC bgApp( *iDefaultAppName ); + TPtrC fgApp( *iDefaultAppName ); + TPtrC fgView( *iDefaultViewName ); + TBool bgFound( EFalse ); + TBool fgFound( EFalse ); + + if ( aEvent.iViewTwoId.iAppUid == TUid::Null() ) + { + // Previous foreground application was closed, get the stored name for + // background application's name. + bgFound = ETrue; + bgApp.Set( iPreviousForegroundApplication ); + } + + for ( TInt i = 0; i < iApplicationSettings.Count(); ++i ) + { + CCFApplicationStateSettings* appSettings = iApplicationSettings[ i ]; + if ( !fgFound && aEvent.iViewOneId.iAppUid == appSettings->Uid() ) + { + fgApp.Set( appSettings->Name() ); + appSettings->GetViewName( aEvent.iViewOneId.iViewUid, fgView ); + fgFound = ETrue; + } + if ( !bgFound && aEvent.iViewTwoId.iAppUid == appSettings->Uid() ) + { + bgApp.Set( appSettings->Name() ); + bgFound = ETrue; + } + if ( bgFound && fgFound ) + { + break; + } + } + + TBool publishFgApp( EFalse ); + TBool publishFgView( EFalse ); + TBool publishBgApp( EFalse ); + + if ( iPreviousForegroundApplication.Compare( fgApp ) != 0 ) + { + publishFgApp = ETrue; + } + else if ( iPreviousForegroundView.Compare( fgView ) != 0 ) + { + publishFgView = ETrue; + } + + if ( bgApp != fgApp ) + { + publishBgApp = ETrue; + } + + iPreviousForegroundApplication.Set( fgApp ); // Store for next round + iPreviousForegroundView.Set( fgView ); + + // Publish foreground application and view contexts. + RThread thread; + + if ( publishFgApp ) + { + iContext->SetTypeL( KApplicationStateForegroundApplicationType ); + iContext->SetValueL( fgApp ); + iCF.PublishContext( *iContext, thread ); + } + + if ( publishFgApp || publishFgView ) + { + iContext->SetTypeL( KApplicationStateForegroundApplicationViewType ); + iContext->SetValueL( fgView ); + iCF.PublishContext( *iContext, thread ); + } + + if ( publishBgApp ) + { + iContext->SetTypeL( KApplicationStateBackgroundApplicationType ); + iContext->SetValueL( bgApp ); + iCF.PublishContext( *iContext, thread ); + } + + // Publish foreground application orientation context + TPtrC fgAppOrientation( ResolveFgAppOrientation( aEvent.iViewOneId.iAppUid ) ); + if( fgAppOrientation.Length() ) + { + // Fg app found + if( fgAppOrientation.Compare( iPreviousOrientation ) != KErrNone ) + { + // Update for next round + iPreviousOrientation.Set( fgAppOrientation ); + + // Fg app orientation changed, publish new context + iContext->SetTypeL( KFgApplicationOrientation ); + iContext->SetValueL( fgAppOrientation ); + iCF.PublishContext( *iContext, thread ); + } + } + + thread.Close(); + } + +//------------------------------------------------------------------------------ +// CApplicationStateSourcePlugIn::ResolveFgAppOrientation +//------------------------------------------------------------------------------ +// +TPtrC CApplicationStateSourcePlugIn::ResolveFgAppOrientation( + const TUid& aUid ) + { + FUNC_LOG; + + TPtrC fgAppOrientation( KNullDesC ); + TInt val = 0; + + // Check cache first + TInt index = FindByUid( aUid ); + if( index != KErrNotFound ) + { + // App found from cache + val = iUidOrientationList[index].iOrientation; + } + else + { + // Get the SID from cenrep and update cache + TInt err = iCRAppOrientation->Get( aUid.iUid, val ); + if( err != KErrNone ) + { + INFO_1( "Application uid: [0x%x] not found, using default orientation", + aUid.iUid ); + val = iDefaultFgAppOrientation; + } + + // Update cache + TUidOrientationPair pair( aUid, val ); + err = iUidOrientationList.Append( pair ); + if( err != KErrNone ) + { + ERROR_2( err, "Failed to add uid: [0x%x], orientation: [%d] pair in cache", + aUid.iUid, val ); + } + } + + // Resolve context value + if( val == CAknAppUiBase::EAppOrientationPortrait ) + { + // Portrait + fgAppOrientation.Set( TPtrC( + KFgApplicationOrientationVal[EFgApplicationOrientationPortrait] ) ); + } + else if( val == CAknAppUiBase::EAppOrientationLandscape ) + { + // Landscape + fgAppOrientation.Set( TPtrC( + KFgApplicationOrientationVal[EFgApplicationOrientationLandscape] ) ); + } + else + { + // Automatic + fgAppOrientation.Set( TPtrC( + KFgApplicationOrientationVal[EFgApplicationOrientationAutomatic] ) ); + } + + return fgAppOrientation; + } + +// ----------------------------------------------------------------------------- +// CApplicationStateSourcePlugIn::InitializeFgApplicationL +// ----------------------------------------------------------------------------- +// +void CApplicationStateSourcePlugIn::InitializeFgApplicationL() + { + FUNC_LOG; + + RWsSession wsSession; + User::LeaveIfError( wsSession.Connect() ); + CleanupClosePushL( wsSession ); + TUid appUid( TUid::Null() ); + + TInt focScr( wsSession.GetFocusScreen() ); + TInt focWndGrp( wsSession.GetFocusWindowGroup() ); + TInt wndGrpPrio( wsSession.GetWindowGroupOrdinalPriority( focWndGrp ) ); + + INFO_1( "CApplicationStateSourcePlugIn::focScr = [%d]", focScr ); + INFO_1( "CApplicationStateSourcePlugIn::focWndGrp = [%d]", focWndGrp ); + INFO_1( "CApplicationStateSourcePlugIn::wndGrpPrio = [%d]", wndGrpPrio ); + + CApaWindowGroupName* wndGrpName = CApaWindowGroupName::NewL( wsSession ); + CleanupStack::PushL( wndGrpName ); + + wndGrpName->ConstructFromWgIdL( focWndGrp ); + + TPtrC appCaption = wndGrpName->Caption(); + TPtrC appName = wndGrpName->AppUid().Name(); + + // if focScr == 0 it's not CoverUi + // if focScr != 0 it's CoverUi + + // if wndGrpPrio == 0 it's S60 application + + if ( ( focScr != 0 ) || ( ( focScr == 0 ) && ( wndGrpPrio == 0 ) ) ) + { + INFO( "CApplicationStateSourcePlugIn::It's CoverUi or S60 application" ); + // It is CoverUi + // or + // It is Not CoverUi and it is S60 application + + appUid = wndGrpName->AppUid(); + INFO_1( "appUid = [0x%x]", appUid.iUid ); + } + else + { + // Default values will still be published + TUid tmpAppUid( TUid::Null() ); + tmpAppUid = wndGrpName->AppUid(); + + INFO( "CApplicationStateSourcePlugIn::It's neiher CoverUi nor S60 application" ); + INFO_1( "appUid = [0x%x]", tmpAppUid.iUid ); + } + + INFO_1( "appCaption = [%S]", &appCaption ); + INFO_1( "appName = [%S]", &appName ); + + CleanupStack::PopAndDestroy( wndGrpName ); + CleanupStack::PopAndDestroy( &wsSession ); + + TPtrC bgApp( *iDefaultAppName ); + TPtrC fgApp( *iDefaultAppName ); + TPtrC fgView( *iDefaultViewName ); + + if ( appUid != TUid::Null() ) + { + for ( TInt i = 0; i < iApplicationSettings.Count(); ++i ) + { + CCFApplicationStateSettings* appSettings = iApplicationSettings[ i ]; + if ( appUid == appSettings->Uid() ) + { + fgApp.Set( appSettings->Name() ); + break; + } + } + } + + iPreviousForegroundApplication.Set( fgApp ); // Store for next round + iPreviousForegroundView.Set( fgView ); + + RThread thread; + + // Publish foreground application + iContext->SetTypeL( KApplicationStateForegroundApplicationType ); + iContext->SetValueL( fgApp ); + iCF.PublishContext( *iContext, thread ); + + // Publish foreground view + iContext->SetTypeL( KApplicationStateForegroundApplicationViewType ); + iContext->SetValueL( fgView ); + iCF.PublishContext( *iContext, thread ); + + // Publish background application + iContext->SetTypeL( KApplicationStateBackgroundApplicationType ); + iContext->SetValueL( bgApp ); + iCF.PublishContext( *iContext, thread ); + + // Publish foreground application orientation + TPtrC fgAppOrientation( ResolveFgAppOrientation( appUid ) ); + iContext->SetTypeL( KFgApplicationOrientation ); + iContext->SetValueL( fgAppOrientation ); + iCF.PublishContext( *iContext, thread ); + + // Store for next round + iPreviousOrientation.Set( fgAppOrientation ); + + thread.Close(); + } + + +//----------------------------------------------------------------------------- +// CApplicationStateSourcePlugIn::ConvertToHex +//----------------------------------------------------------------------------- +// +TInt CApplicationStateSourcePlugIn::ConvertToHex( const TDesC& aString, + TUint32& aValue ) + { + FUNC_LOG; + + TInt err = KErrNone; + TLex lex( aString ); + + // Get rid of '0x' + const TInt skip = 2; + lex.Inc( skip ); + if( lex.BoundedVal( aValue, EHex, KLimit ) != KErrNone ) + { + err = KErrNotFound; + } + return err; + } + +//------------------------------------------------------------------------------ +// CApplicationStateSourcePlugIn::FindByUid +//------------------------------------------------------------------------------ +// +TInt CApplicationStateSourcePlugIn::FindByUid( const TUid& aUid ) const + { + FUNC_LOG; + + TInt index = KErrNotFound; + for( TInt i = 0; i < iUidOrientationList.Count(); i++ ) + { + if( iUidOrientationList[i].iUid == aUid ) + { + index = i; + break; + } + } + return index; + }