diff -r 000000000000 -r 2f259fa3e83a uifw/AvKon/src/AknTasHook.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/AvKon/src/AknTasHook.cpp Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,677 @@ +/* +* 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: Avkon testability hook class definitions. +* +*/ + + +// INCLUDES +#include +#include +#include "AknBatteryStrength.h" +#include "AknSignalStrength.h" +#include +#include +#include + +// CONSTANTS +const TUid KUidTasHook = { 0xE000DEC4 }; +const TInt KTasHookingOff = 0; +const TInt KTasHookingOn = 1; + +// MACROS + + /** + * DEBUGPRINT + * + * Simple wrapper macro for the RDebug::Print utility. + * + * Usage: + * + * DEBUGPRINT( ( _L( "CAknTasHook::ConstructL: Error %d in doing stuff" ), error ) ) + * + */ + #ifdef _DEBUG + #define DEBUGPRINT( aFormatString ) { RDebug::Print aFormatString; } + #else + #define DEBUGPRINT( aFormatString ) {} + #endif + +// FORWARD DECLARATIONS +class CAknTasClassInfo; +class CAknTasObjectInfo; + +// CLASS DEFINITIONS + +CAknTasClassInfo::CAknTasClassInfo() : + iClassName( NULL ) + { + } + +CAknTasClassInfo::~CAknTasClassInfo() + { + delete iClassName; + } + +void CAknTasClassInfo::ConstructL( TDesC& aClassName ) + { + // Allocate a copy of the given descriptor and take ownership of it + iClassName = aClassName.AllocL(); + } + +const TDesC& CAknTasClassInfo::GetClassName() const + { + return *iClassName; + } + +TInt CAknTasClassInfo::MatchName( + const CAknTasClassInfo& aInfo1, + const CAknTasClassInfo& aInfo2 ) + { + if ( aInfo1.GetClassName() == aInfo2.GetClassName() ) + { + return 1; + } + return 0; + } + +CAknTasObjectInfo::CAknTasObjectInfo() + { + } + +CAknTasObjectInfo::~CAknTasObjectInfo() + { + if ( iClassInfoArray ) + { + iClassInfoArray->ResetAndDestroy(); + delete iClassInfoArray; + } + } + +void CAknTasObjectInfo::ConstructL( + TAny* aObjPtr, + TAknTasHookObjectType aObjType ) + { + iObjPtr = aObjPtr; // not owned + if ( aObjPtr ) + { + iClassInfoArray = new ( ELeave ) RPointerArray; // owned + iControlKey = TUint32( aObjPtr ); + iObjType = aObjType; + } + else + { + iControlKey = 0; + } + } + +TInt CAknTasObjectInfo::MatchByControl( + const CAknTasObjectInfo& aInfo1, + const CAknTasObjectInfo& aInfo2 ) + { + if ( aInfo1.iControlKey == aInfo2.iControlKey ) + { + return 1; + } + return 0; + } + +void CAknTasObjectInfo::AddL( CAknTasClassInfo* aObjPtr ) + { + iClassInfoArray->AppendL( aObjPtr ); + } + +EXPORT_C TBool CAknTasObjectInfo::IsA( TPtrC aClassName ) + { + CAknTasClassInfo* classInfo = NULL; + TRAPD( err, + classInfo = new ( ELeave ) CAknTasClassInfo(); + CleanupStack::PushL( classInfo ); + classInfo->ConstructL( aClassName ); + CleanupStack::Pop( classInfo ) ); + if ( err ) + { + if ( classInfo ) + { + CleanupStack::PopAndDestroy( classInfo ); + } + return EFalse; + } + + TIdentityRelation matcher( CAknTasClassInfo::MatchName ); + TInt position = iClassInfoArray->Find( classInfo, matcher ); + delete classInfo; + if ( position != KErrNotFound ) + { + classInfo = ( *iClassInfoArray )[position]; + return ETrue; + } + return EFalse; + } + +// +// Heap descriptor ownership passed to caller! +// +EXPORT_C HBufC* CAknTasObjectInfo::GetClassNames() + { + // Sum up the class name lengths and add room for the separators + TInt bufLength( 0 ); + for ( TInt i = 0; i < iClassInfoArray->Count(); i++ ) + { + bufLength += ( *iClassInfoArray )[i]->GetClassName().Length() + 1; + } + + // Create a buffer of needed length and make it empty + HBufC* buf = NULL; + TRAPD( err, + buf = HBufC::NewLC( bufLength ); + CleanupStack::Pop( buf ) ); + if ( err ) + { + return NULL; + } + TPtr modifiableBuf = buf->Des(); + modifiableBuf.Zero(); + + if ( iClassInfoArray->Count() <= 0 ) + { + return buf; + } + + // Append class names and separators + for ( TInt i = 0; i < iClassInfoArray->Count(); i++ ) + { + modifiableBuf.Append( ( *iClassInfoArray )[i]->GetClassName() ); + + if ( i + 1 < iClassInfoArray->Count() ) + { + modifiableBuf.Append( _L( ":" ) ); + } + } + + return buf; + } + +EXPORT_C TAny* CAknTasObjectInfo::GetControl() const + { + return iObjPtr; + } + +EXPORT_C TAknTasHookObjectType CAknTasObjectInfo::Type() const + { + return iObjType; + } + +CAknTasHook::CAknTasHook() : + CCoeStatic( KUidTasHook ), + iTasHookingEnabled( EFalse ), + iTasHookStoringEnabled( EFalse ) + { + } + +CAknTasHook* CAknTasHook::InstanceL() + { + CAknTasHook* instance = + static_cast ( CCoeEnv::Static( KUidTasHook ) ); + if ( !instance ) + { + instance = new ( ELeave ) CAknTasHook(); + CleanupStack::PushL( instance ); + instance->ConstructL(); + CleanupStack::Pop( instance ); + } + return instance; + } + +CAknTasHook* CAknTasHook::Self() + { + CAknTasHook* instance = + static_cast ( CCoeEnv::Static( KUidTasHook ) ); + if ( !instance ) + { + return NULL; + } + return instance; + } + +CAknTasHook::~CAknTasHook() + { + delete iTasPlugin; + REComSession::FinalClose(); + if ( iHookingNotifyHandler ) + { + iHookingNotifyHandler->StopListening(); + delete iHookingNotifyHandler; + } + if ( iHookStoringNotifyHandler ) + { + iHookStoringNotifyHandler->StopListening(); + delete iHookStoringNotifyHandler; + } + delete iTasHookingRepo; + if ( iObjectInfoArray ) + { + iObjectInfoArray->ResetAndDestroy(); + delete iObjectInfoArray; + } + } + +void CAknTasHook::ConstructL() + { + iObjectInfoArray = new ( ELeave ) RPointerArray; // owned + + // Connect to TAS hooking CenRep repository + TRAPD( error, iTasHookingRepo = CRepository::NewL( KCRUidTasHooking ) ); + if ( error != KErrNone ) + { + DEBUGPRINT( ( _L( " CAknTasHook::ConstructL: Error %d in connecting to key 0x%x" ), error, KCRUidTasHooking.iUid ) ) + User::Leave( error ); + } + + // Process the initial values and start listening + // for key changes in this repository + TRAP( error, iHookingNotifyHandler = CreateNotifyHandlerL( *iTasHookingRepo, KTasHooking ) ); + if ( error != KErrNone ) + { + DEBUGPRINT( ( _L( " CAknTasHook::ConstructL: Error %d in creating CenRep notify handler" ), error ) ) + User::Leave( error ); + } + TRAP( error, iHookingNotifyHandler->StartListeningL() ); + if ( error != KErrNone ) + { + DEBUGPRINT( ( _L( " CAknTasHook::ConstructL: Error %d in starting to listen" ), error ) ) + User::Leave( error ); + } + TRAP( error, iHookStoringNotifyHandler = CreateNotifyHandlerL( *iTasHookingRepo, KTasHookStoring ) ); + if ( error != KErrNone ) + { + DEBUGPRINT( ( _L( " CAknTasHook::ConstructL: Error %d in creating CenRep notify handler" ), error ) ) + User::Leave( error ); + } + TRAP( error, iHookStoringNotifyHandler->StartListeningL() ); + if ( error != KErrNone ) + { + DEBUGPRINT( ( _L( " CAknTasHook::ConstructL: Error %d in starting to listen" ), error ) ) + User::Leave( error ); + } + } + +CCenRepNotifyHandler* CAknTasHook::CreateNotifyHandlerL( + CRepository& aRepository, + TUint32 aKey ) + { + // Process the initial value, the 1st notication is only received when the + // value changes so we need to see if the hooking has already been activated + TInt initialValue; + TInt error = aRepository.Get( aKey, initialValue ); + if ( error != KErrNone ) + { + DEBUGPRINT( ( _L( " CAknTasHook::CreateNotifyHandlerL: Error %d in getting key value" ), error ) ) + User::Leave( error ); + } + else + { + HandleNotifyInt( aKey, initialValue ); + } + + // Create a new notify handler for the given integer key + return CCenRepNotifyHandler::NewL( *this, aRepository, CCenRepNotifyHandler::EIntKey, aKey ); + } + +TBool CAknTasHook::Initialized() + { + if ( iObjectInfoArray ) + { + return ETrue; + } + return EFalse; + } + +EXPORT_C void CAknTasHook::AddL( + TAny* aObjPtr, + TPtrC aStrPtr, + TAknTasHookObjectType aObjType ) + { + if ( !aObjPtr ) + { + return; + } + + CAknTasHook* mePtr = InstanceL(); + if ( mePtr ) + { + mePtr->AddInfoL( aObjPtr, aStrPtr, aObjType ); + } + } + +void CAknTasHook::AddInfoL( + TAny* aObjPtr, + TPtrC aStrPtr, + TAknTasHookObjectType aObjType ) + { + if ( iTasHookStoringEnabled ) + { + CAknTasObjectInfo* objInfo = new ( ELeave ) CAknTasObjectInfo(); + CleanupStack::PushL( objInfo ); + objInfo->ConstructL( aObjPtr, aObjType ); + CleanupStack::Pop( objInfo ); + CAknTasClassInfo* classInfo = new ( ELeave ) CAknTasClassInfo(); + CleanupStack::PushL( classInfo ); + classInfo->ConstructL( aStrPtr ); + CleanupStack::Pop( classInfo ); + + if ( iObjectInfoArray->Count() <= 0 ) + { + objInfo->AddL( classInfo ); + iObjectInfoArray->AppendL( objInfo ); + return; + } + + TIdentityRelation matcher( CAknTasObjectInfo::MatchByControl ); + TInt position = iObjectInfoArray->Find( objInfo, matcher ); + if ( position != KErrNotFound ) + { + delete objInfo; + objInfo = ( *iObjectInfoArray )[position]; + } + else + { + iObjectInfoArray->AppendL( objInfo ); + } + objInfo->AddL( classInfo ); + } + } + +EXPORT_C CAknTasObjectInfo* CAknTasHook::Get( TAny* aObjPtr ) + { + CAknTasHook* mePtr = Self(); + if ( !mePtr->iTasHookingEnabled ) + { + return NULL; + } + + if ( mePtr ) + { + return mePtr->GetInfo( aObjPtr ); + } + + return NULL; + } + +CAknTasObjectInfo* CAknTasHook::GetInfo( TAny* aObjPtr ) + { + CAknTasObjectInfo* objInfo = NULL; + TRAPD( err, + objInfo = new ( ELeave ) CAknTasObjectInfo(); + CleanupStack::PushL( objInfo ); + objInfo->ConstructL( aObjPtr ) ); + CleanupStack::Pop( objInfo ); + if ( err ) + { + if ( objInfo ) + { + CleanupStack::PopAndDestroy( objInfo ); + } + return NULL; + } + + TIdentityRelation matcher( CAknTasObjectInfo::MatchByControl ); + TInt position = iObjectInfoArray->Find( objInfo, matcher ); + delete objInfo; + if ( position != KErrNotFound ) + { + return ( *iObjectInfoArray )[position]; + } + else + { + return NULL; + } + } + +TBool CAknTasHook::ExistsL( TAny* aObjPtr ) + { + CAknTasHook* mePtr = InstanceL(); + return mePtr->InfoExistsL( aObjPtr ); + } + +TBool CAknTasHook::InfoExistsL( TAny* aObjPtr ) + { + if ( iObjectInfoArray->Count() <= 0 ) + { + return EFalse; + } + + CAknTasObjectInfo* objInfo = new ( ELeave ) CAknTasObjectInfo(); + CleanupStack::PushL( objInfo ); + objInfo->ConstructL( aObjPtr ); + CleanupStack::Pop( objInfo ); + + TIdentityRelation matcher( CAknTasObjectInfo::MatchByControl ); + TInt position = iObjectInfoArray->Find( objInfo, matcher ); + delete objInfo; + if ( position != KErrNotFound ) + { + return ETrue; + } + else + { + return EFalse; + } + } + +EXPORT_C void CAknTasHook::Remove( TAny* aObjPtr ) + { + CAknTasHook* mePtr = Self(); + if ( mePtr ) + { + TInt err( KErrNone ); + TRAP( err, mePtr->RemoveInfoL( aObjPtr ) ); + } + } + +void CAknTasHook::RemoveInfoL( TAny* aObjPtr ) + { + if ( iTasHookStoringEnabled ) + { + if ( iObjectInfoArray->Count() <= 0 ) + { + return; + } + + CAknTasObjectInfo* objInfo = new ( ELeave ) CAknTasObjectInfo(); + CleanupStack::PushL( objInfo ); + objInfo->ConstructL( aObjPtr ); + CleanupStack::Pop( objInfo ); + + TIdentityRelation matcher( CAknTasObjectInfo::MatchByControl ); + TInt position = iObjectInfoArray->Find( objInfo, matcher ); + delete objInfo; + if ( position != KErrNotFound ) + { + objInfo = ( *iObjectInfoArray )[position]; + iObjectInfoArray->Remove( position ); + delete objInfo; + } + } + } + +EXPORT_C RPointerArray* CAknTasHook::GetAll() + { + if ( !iTasHookingEnabled ) + { + return NULL; + } + return iObjectInfoArray; + } + +EXPORT_C void CAknTasHook::GetAknUiLC( MTasObject& aParentApplication ) + { + if ( !iTasHookingEnabled ) + { + return; + } + + TInt numObjects = iObjectInfoArray->Count(); + + for ( TInt i = 0; i < numObjects; i++ ) + { + CAknTasObjectInfo* objInfo = ( *iObjectInfoArray )[i]; + + if ( objInfo->IsA( _L( "CAknBatteryStrength" ) ) ) + { + if ( !CheckSanityL( ( CCoeControl* ) objInfo->GetControl() ) ) + { + continue; + } + CAknBatteryStrength* battery = + static_cast( objInfo->GetControl() ); + if ( battery ) + { + MTasObject& tasObj = aParentApplication.AddObjectL(); + //tasObj.AddAttributeL( _L( "Id" ), objInfo->iControlKey ); + tasObj.SetNameL( _L( "CAknBatteryStrength" ) ); + tasObj.SetTypeL( _L( "indicator" ) ); + tasObj.SetIdL( objInfo->iControlKey ); + tasObj.AddAttributeL( _L( "Level" ), battery->BatteryLevel() ); + tasObj.AddAttributeL( _L( "Recharging" ), battery->Recharging() ); + AddCommonCoeInfoL( ( CCoeControl* ) objInfo->GetControl(), tasObj ); + } + } + else if ( objInfo->IsA( _L( "CAknSignalStrength" ) ) ) + { + if ( !CheckSanityL( ( CCoeControl* )objInfo->GetControl() ) ) + { + continue; + } + CAknSignalStrength* signal = + static_cast( objInfo->GetControl() ); + if ( signal ) + { + MTasObject& tasObj = aParentApplication.AddObjectL(); + //tasObj.AddAttributeL( _L( "Id" ), objInfo->iControlKey ); + tasObj.SetNameL( _L( "CAknSignalStrength" ) ); + tasObj.SetTypeL( _L( "indicator" ) ); + tasObj.SetIdL( objInfo->iControlKey ); + tasObj.AddAttributeL( _L( "Level" ), signal->SignalLevel() ); + AddCommonCoeInfoL( ( CCoeControl* ) objInfo->GetControl(), tasObj ); + } + } + } + } + +void CAknTasHook::AddCommonCoeInfoL( CCoeControl* aObjPtr, MTasObject& aObjectInfo ) + { + //add positional details + TRect absoluteRect( 0, 0, 0, 0 ); + if ( aObjPtr->OwnsWindow() ) + { + RDrawableWindow* window = aObjPtr->DrawableWindow(); + if ( window ) + { + TRect tempRect( window->AbsPosition(), window->Size() ); + absoluteRect = tempRect; + } + } + else + { + TRect tempRect( aObjPtr->PositionRelativeToScreen(), aObjPtr->Size() ); + absoluteRect = tempRect; + } + + aObjectInfo.AddAttributeL( _L( "X" ), absoluteRect.iTl.iX ); + aObjectInfo.AddAttributeL( _L( "Y" ), absoluteRect.iTl.iY ); + aObjectInfo.AddAttributeL( _L( "Width" ), absoluteRect.Width() ); + aObjectInfo.AddAttributeL( _L( "Height" ), absoluteRect.Height() ); + + //some general details + aObjectInfo.AddAttributeL( _L( "Visible" ), ( aObjPtr->IsVisible()? _L( "TRUE" ) : _L( "FALSE" ) ) ); + aObjectInfo.AddAttributeL( _L( "Focused" ), ( aObjPtr->IsFocused()? _L( "TRUE" ): _L( "FALSE" ) ) ); + aObjectInfo.AddAttributeL( _L( "Dimmed" ), ( aObjPtr->IsDimmed()? _L( "TRUE" ): _L( "FALSE" ) ) ); + aObjectInfo.AddAttributeL( _L( "HasBorder" ), ( aObjPtr->HasBorder()? _L( "TRUE" ): _L( "FALSE" ) ) ); + } + +void CAknTasHook::HandleNotifyInt( TUint32 aId, TInt aNewValue ) + { + if ( aId == KTasHooking ) + { + if ( aNewValue == KTasHookingOn && !iTasHookingEnabled ) + { + TRAPD( errorCreate, iTasPlugin = CAknTasPluginInterface::NewL() ); + if ( errorCreate != KErrNone ) + { + iTasHookingEnabled = EFalse; + return; + } + TRAPD( errorSet, iTasPlugin->SetHookInterfaceL( InstanceL() ) ); + if ( errorSet != KErrNone ) + { + delete iTasPlugin; + iTasPlugin = NULL; + iTasHookingEnabled = EFalse; + return; + } + iTasHookingEnabled = ETrue; + } + else if ( aNewValue == KTasHookingOff && iTasHookingEnabled ) + { + delete iTasPlugin; + iTasPlugin = NULL; + iTasHookingEnabled = EFalse; + } + else + { + // Invalid value + } + } + else if ( aId == KTasHookStoring ) + { + if ( aNewValue == KTasHookingOn ) + { + iTasHookStoringEnabled = ETrue; + } + else if ( aNewValue == KTasHookingOff ) + { + iTasHookStoringEnabled = EFalse; + } + else + { + // Invalid value + } + } + else + { + // Wrong key + } + } + +TBool CAknTasHook::CheckSanityL( CCoeControl* aControl ) + { + // check the sanity of the object + if ( !aControl || + !aControl->DrawableWindow() || + !aControl->ControlEnv() || + !aControl->IsVisible() ) + { + return EFalse; + } + + if ( !iTasPlugin->IsControlVisible( *aControl ) ) + { + return EFalse; + } + + return ETrue; + } + +// End of File