bluetoothengine/btnotif/src/BTNotifier.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 19 Feb 2010 22:59:18 +0200
branchRCL_3
changeset 6 6a29d5ad0713
parent 0 f63038272f30
child 13 b6f55cd40afd
permissions -rw-r--r--
Revision: 201003 Kit: 201007

/*
* Copyright (c) 2002 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:  Declares Bluetooth notifiers base class.
*
*/


// INCLUDE FILES
#include <centralrepository.h> 
#include <CoreApplicationUIsSDKCRKeys.h>

#include <settingsinternalcrkeys.h>
#include <e32property.h>

#include <btengsettings.h>
#include <btengprivatecrkeys.h>
#include <btengconnman.h>
#include <btengutil.h>
#include <StringLoader.h>    // Localisation stringloader
#include <BTNotif.rsg>       // Own resources
#include <featmgr.h>            // Feature Manager API
#include <utf.h>             // CnvUtfConverter
#include <bluetoothuiutil.h>
#include "btnotifier.h"      // Own class definition
#include "btNotifDebug.h"    // Debugging macros
#include "btnotiflock.h"
#include "btnotif.hrh"       // define MaxNameLength
#include "btnotifpanic.h"
#include "btnotifnameutils.h"

#ifdef __SERIES60_HELP
#include <hlplch.h>
#include <csxhelp/bt.hlp.hrh> // The bt hrh info is needed, for help launching
#endif

// CONSTANTS
const TInt KBTNAutolockEnabled = 1;

// The following definitions are used to implement checking of connection/pairing
// request frequency

// if a new connection is made quicker than CONNECT_ADD_TIME after the old one, 
// then the saved time is added with CONNECT_ADD_TIME.
#define CONNECT_ADD_TIME TTimeIntervalSeconds(10)

// if the saved time is later than now+DENY_THRESHOLD, start rejecting incoming connections
// from unpaired devices.
#define DENY_THRESHOLD	 TTimeIntervalSeconds(30)

// if the user denies incoming connection the saved time goes this much in the future.
#define REJECT_ADD_TIME TTimeIntervalSeconds(31)


// ================= MEMBER FUNCTIONS =======================

// ----------------------------------------------------------
// CBTNotifierBase::CBTNotifierBase
// C++ default constructor can NOT contain any code, that
// might leave. Sets the AOs priority and puts
// itself to the active scheduler stack.
// ----------------------------------------------------------
//
CBTNotifierBase::CBTNotifierBase() 
    {
    }

// ----------------------------------------------------------
// CBTNotifierBase::ConstructL
// Symbian 2nd phase constructor can leave.
// Create registry object and open resource file.
// ----------------------------------------------------------
//
void CBTNotifierBase::ConstructL()
    {
	// Sets up TLS, must be done before FeatureManager is used.
	FeatureManager::InitializeLibL();
	iIsCoverUI = ( FeatureManager::FeatureSupported( KFeatureIdCoverDisplay ) ) 
                    ? ETrue : EFalse; 	
	// Frees the TLS. Must be done after FeatureManager is used.
    FeatureManager::UnInitializeLib(); 

    iBTEngSettings = CBTEngSettings::NewL();
    iDevMan = CBTEngDevMan::NewL( this );
    iNotifUiUtil = CBTNotifUIUtil::NewL( iIsCoverUI );
    }

// ----------------------------------------------------------
// Destructor.
// ----------------------------------------------------------
//
CBTNotifierBase::~CBTNotifierBase()
    {
    FLOG(_L("[BTNOTIF]\t CBTNotifierBase::~CBTNotifierBase()"));    
    Cancel();
    FLOG(_L("[BTNOTIF]\t CBTNotifierBase::~CBTNotifierBase() -- Done"));    
    }

// ----------------------------------------------------------
// CBTNotifierBase::Release
// Release itself. Call to destructor.
// ----------------------------------------------------------
//
void CBTNotifierBase::Release()
    {
    delete this;
    }


// ----------------------------------------------------------
// CBTNotifierBase::Info
// Return registered information.
// ----------------------------------------------------------
//
CBTNotifierBase::TNotifierInfo CBTNotifierBase::Info() const
    {
    return iInfo;
    }

// ----------------------------------------------------------
// CBTNotifierBase::StartL
// Synchronic notifier launch. Does nothing here.
// ----------------------------------------------------------
//
TPtrC8 CBTNotifierBase::StartL(const TDesC8& /*aBuffer*/)
    {
    TPtrC8 ret(KNullDesC8);
    return (ret);
    }

// ----------------------------------------------------------
// CBTNotifierBase::StartL
// Asynchronic notifier launch.
// ----------------------------------------------------------
//
void CBTNotifierBase::StartL(const TDesC8& aBuffer, TInt aReplySlot, const RMessagePtr2& aMessage)
    {
    if( !iNotifUiUtil )
        {
        iNotifUiUtil = CBTNotifUIUtil::NewL( iIsCoverUI );    
        }
    
    TRAPD(err, GetParamsL(aBuffer, aReplySlot, aMessage));
    if (err)
        {
        CompleteMessage(err);
        }
    }

// ----------------------------------------------------------
// CBTNotifierBase::Cancel
// Cancelling method.
// ----------------------------------------------------------
//
void CBTNotifierBase::Cancel()
    {
    FLOG(_L("[BTNOTIF]\t CBTNotifierBase::Cancel()"));    

    delete iNotifUiUtil;
    iNotifUiUtil = NULL;
    
	delete iBTEngSettings;
    iBTEngSettings = NULL;

    delete iDevMan;
    iDevMan = NULL;
    
    delete iDevice;
    iDevice = NULL;
    
    if (iDeviceArray)
        {
        iDeviceArray->ResetAndDestroy();
        delete iDeviceArray;
        iDeviceArray = NULL;
        }
        
	CompleteMessage(KErrCancel);        
    }

// ----------------------------------------------------------
// CBTNotifierBase::UpdateL
// Notifier update. Not supported.
// ----------------------------------------------------------
//
TPtrC8 CBTNotifierBase::UpdateL(const TDesC8& /*aBuffer*/)
    {
    TPtrC8 ret(KNullDesC8);
    return (ret);
    }


// ----------------------------------------------------------
// CBTNotifierBase::AutoLockOnL
// ----------------------------------------------------------
//
TBool CBTNotifierBase::AutoLockOnL()
    {
    FLOG(_L("[BTNOTIF]\t CBTNotifierBase::AutoLockOnL()"));

    TBool result = EFalse;
    TInt status = KBTNAutolockEnabled;
    
    // Connecting and initialization:
	CRepository* repository = CRepository::NewL(KCRUidSecuritySettings);
		
	repository->Get(KSettingsAutolockStatus, status);
		
	// Closing connection:
	delete repository;
		
    if ( status == KBTNAutolockEnabled )
        {
        result = ETrue;
        }

    FTRACE(FPrint(_L("[BTNOTIF]\t CBTNotifierBase::AutoLockOnL() completed with %d"), result ));

    return result;
    }

// ----------------------------------------------------------
// CBTNotifierBase::CheckAndSetPowerOnL
// The note or query to be shown depends on two SharedData flags
// ----------------------------------------------------------
//
TBool CBTNotifierBase::CheckAndSetPowerOnL()
    {
    FLOG(_L("[BTNOTIF]\t CBTNotifierBase::CheckAndSetPowerOnL()"));

	TBTPowerStateValue powerState( EBTPowerOff );
    // Get current power status
    //
    User::LeaveIfError( iBTEngSettings->GetPowerState( powerState ) );

    // If power is off, turn it on
    //
    if ( powerState == EBTPowerOff )
        {
        TInt offlineModeOff( 1 );    // possible values are 0 and 1
        TInt activationEnabled( 0 ); // possible values are 0 and 1
        
        // Offline mode on?
        CRepository* repository = CRepository::NewL(KCRUidCoreApplicationUIs);
        repository->Get(KCoreAppUIsNetworkConnectionAllowed, offlineModeOff);
        delete repository;
        
        // BT Activation enabled?
        repository = CRepository::NewL(KCRUidBluetoothEngine);
        repository->Get(KBTEnabledInOffline, activationEnabled);
        delete repository;
        
        // Choose user interaction
        //
        if ( !offlineModeOff && !activationEnabled )
            {
            // Show user that feature is disabled:
            iNotifUiUtil->ShowInfoNoteL( R_BT_OFFLINE_DISABLED, ECmdShowBtOfflineDisableNote );
            return EFalse; // Bluetooth can't be set on.
            }
        else
            {
            // Choose query
            //
            TInt keypress( 0 );	
            if ( offlineModeOff )
                {
                keypress = iNotifUiUtil->ShowQueryL( KErrNone, R_BT_POWER_IS_OFF_QUERY, ECmdShowBtIsOffDlg );
                }
            else
                {
                keypress = iNotifUiUtil->ShowQueryL( KErrNone, R_BT_ACTIVATE_IN_OFFLINE_QUERY, 
                        ECmdShowBtActivateInOfflineDlg );
				}

            if( keypress )  // User answered YES
                { 
                //Check if the local name has been set. If not ask user to set name
                
				TBool ok = IsLocalNameModifiedL();
    			if( !ok )
    				{
      				ok = AskLocalBTNameQueryL();
    				}
               if ( ok )
			       {  
                	ok = ( iBTEngSettings->SetPowerState( EBTPowerOn ) ) ? EFalse : ETrue;
                	}
                return ok;
                }
            else // User has cancelled the dialog
                {
                FLOG(_L("[BTNOTIF]\t CBTNotifierBase::CheckAndSetPowerOnL(), dialog canceled"));
                return EFalse;
                }                    
            }
        }
    return ETrue;
    }
    
// ----------------------------------------------------------
// CBTNotifierBase::AskLocalBTNameQueryL()
// ----------------------------------------------------------
//
TBool CBTNotifierBase::AskLocalBTNameQueryL()
    {
	FLOG(_L("[BTNOTIF]\t CBTNotifierBase::AskLocalBTNameQueryL() >>"));
	
	TBTDeviceName tempNameBuffer;
    // Cut the excess part of the name away. The query can handle only 
    // KBTUIMaxNameLength characters.
    //
    if( tempNameBuffer.Length() > KBTUIMaxNameLength )
     {
     tempNameBuffer.SetLength( KBTUIMaxNameLength );
     }

    //Get default name if given by e.g. phone product
    (void) RProperty::Get( KPropertyUidBluetoothCategory, 
                           KPropertyKeyBluetoothGetDeviceName, tempNameBuffer );
    
    if( !tempNameBuffer.Length() )
        {
        (void) RProperty::Get( KPropertyUidBluetoothCategory, 
                KPropertyKeyBluetoothGetDeviceName, tempNameBuffer );
        }
    
    if( !tempNameBuffer.Length() )
        {
        RBTRegServ btRegServ;
        RBTLocalDevice btReg;
        TBTLocalDevice localDev;

        TInt err = btRegServ.Connect();
        if( !err )
            {
            err = btReg.Open( btRegServ );
            } 
        if( !err )
            {
            // Read the BT local name from BT Registry.
            err = btReg.Get( localDev );
            }
        if( !err )
            {
            // The error can be > 0 if there are unconverted characters.
            err = CnvUtfConverter::ConvertToUnicodeFromUtf8( tempNameBuffer, localDev.DeviceName() );
            }
        btReg.Close();
        btRegServ.Close();
        }

    TInt keypress = iNotifUiUtil->ShowTextInputQueryL( tempNameBuffer, 
            R_BT_ENTER_LOCAL_NAME_QUERY, ECmdBTnotifUnavailable );
    
    if( keypress )  // User has accepted the dialog
        {
        AknTextUtils::StripCharacters(tempNameBuffer,  KAknStripListControlChars);
        tempNameBuffer.TrimAll();   // Remove extra spaces
        // If name was full of invalid chars, it becomes empty after above cleanup. 
        if( tempNameBuffer.Length() ) 
            {
            TInt err = iBTEngSettings->SetLocalName( tempNameBuffer );
            FLOG(_L("[BTNOTIF]\t CBTNotifierBase::AskLocalBTNameQueryL() <<"));
            return (err) ? EFalse : ETrue;    
            }
        else
            {
            FLOG(_L("[BTNOTIF]\t CBTNotifierBase::AskLocalBTNameQueryL() << failed"));
            return EFalse;
            }
        }
    else
        {
        FLOG(_L("[BTNOTIF]\t CBTNotifierBase::AskLocalBTNameQueryL() << cancelled"));
        return EFalse;
        }
    }

// ---------------------------------------------------------------------------------
// CBTNotifierBase::IsExistingConnectionToAudioL
// Check if there is any existing connection to audio profiles from the same device
// ---------------------------------------------------------------------------------
TBool CBTNotifierBase::IsExistingConnectionToAudioL( const TBTDevAddr& aDevAddr )
    {
    FLOG(_L("[BTNOTIF]\t CBTNotifierBase::IsExistingConnectionToAudioL()"));
    CBTEngConnMan* connMan = CBTEngConnMan::NewL();
    TBTEngConnectionStatus conntatus( EBTEngNotConnected );
    (void) connMan->IsConnected(aDevAddr,conntatus);      
    delete connMan;
    FLOG(_L("[BTNOTIF]\t CBTNotifierBase::IsExistingConnectionToAudioL() complete"));
    return ( conntatus==EBTEngConnected || conntatus==EBTEngConnecting );
    }

// ---------------------------------------------------------------------------
// CBTNotifierBase::IsLocalNameModified
// Checks from central repository whether the Bluetooth friendly name 
// has been modified .
// ---------------------------------------------------------------------------
//
TBool CBTNotifierBase::IsLocalNameModifiedL()
	{
	FLOG(_L("[BTNOTIF]\t CBTNotifierBase::IsLocalNameModified()"));   
    CRepository* cenRep = CRepository::NewL( KCRUidBTEngPrivateSettings );
    TInt val( EBTLocalNameDefault );
    (void) cenRep->Get( KBTLocalNameChanged, val );
    delete cenRep;
    FLOG(_L("[BTNOTIF]\t CBTNotifierBase::IsLocalNameModified() complete"));
    return val == EBTLocalNameSet;
    }


void CBTNotifierBase::GetDeviceFromRegL(const TBTDevAddr& aAddr)
    {
    FLOG(_L("[BTNOTIF]\t CBTNotifierBase::GetDeviceFromRegL"));
    __ASSERT_DEBUG(iDevice, BTNOTIF_PANIC(EiDeviceNullWhenCallingGetDeviceFromRegL));

    TBTRegistrySearch mySearch;
    mySearch.FindAddress( aAddr );
    iDeviceArray = new (ELeave) CBTDeviceArray(1);
    if( !iDevMan )
        {
        iDevMan = CBTEngDevMan::NewL( this );    
        }
    TInt err = iDevMan->GetDevices( mySearch, iDeviceArray );
    if(err)
        {
        FTRACE(FPrint(_L("[BTNOTIF]\t CBTNotifierBase::GetDeviceFromRegL iDevMan->GetDevices error = %d"), err));
        DoHandleGetDevicesCompleteL(err, NULL);
        }
    FLOG(_L("[BTNOTIF]\t CBTNotifierBase::GetDeviceFromRegL done"));
    }

// ----------------------------------------------------------
// CBTNotifierBase::QueryBlockDeviceL
// Opens a query that returns wether or not user wants the device blocked
// ----------------------------------------------------------
void CBTNotifierBase::QueryBlockDeviceL()
    {
    FLOG(_L("[BTNOTIF]\t CBTNotifierBase::QueryBlockDeviceL()"));
    __ASSERT_DEBUG( iNotifUiUtil->IsQueryReleased(), User::Panic( _L("CBTNotifierBase - iYesNoDlg not released!"), KErrAlreadyExists ) );
    
    TBTDeviceName bName;
    BtNotifNameUtils::GetDeviceDisplayName(bName, iDevice);

    HBufC* header= StringLoader::LoadLC( R_BT_BLOCK_DEVICE_HEADER );

    TInt resId = IsUserAwarePaired( iDevice->AsNamelessDevice() ) ? 
        R_BT_BLOCK_PAIRED_DEVICE_NOHELP : R_BT_BLOCK_DEVICE_NOHELP;
	
    RBuf stringholder;
    stringholder.CleanupClosePushL();
    BluetoothUiUtil::LoadResourceAndSubstringL( stringholder, resId, bName, 0 );

	TInt keypress = iNotifUiUtil->ShowMessageQueryL( stringholder, *header, 
	        R_BT_GENERIC_MESSAGE_QUERY, CAknQueryDialog::EConfirmationTone );
    
    CleanupStack::PopAndDestroy(&stringholder);                   
    CleanupStack::PopAndDestroy(header);  

    if( keypress )// user replied "Yes"
        {
        DoBlockDevice();
        }
    else  // user replied "No" 
        {
        CompleteMessage(KErrCancel);        
        } 
    FLOG(_L("[BTNOTIF]\t CBTNotifierBase::QueryBlockDeviceL() complete"));   
    }

void CBTNotifierBase::DoBlockDevice()
    {
    FLOG(_L("[BTNOTIF]\t CBTNotifierBase::DoBlockDevice()"));
    TBTDeviceSecurity deviceSecurity = iDevice->GlobalSecurity();
    deviceSecurity.SetBanned(ETrue);
    deviceSecurity.SetNoAuthenticate(EFalse);
    deviceSecurity.SetNoAuthorise(EFalse);
    iDevice->SetGlobalSecurity(deviceSecurity);
    iDevice->DeleteLinkKey();
 
    iBTRegistryQueryState = ESetDeviceBlocked;
    if( !iDevMan )
        {
        iDevMan = CBTEngDevMan::NewL( this );    
        }
    TInt devManErr = iDevMan->ModifyDevice( *iDevice );     
            
    // if error, complete message, otherwise waiting for devman callback
    //
    if(devManErr != KErrNone)
        CompleteMessage(devManErr); 
    }

void CBTNotifierBase::ChangeAuthorizeState( TBool aTrust )
    {
    FLOG(_L("[BTNOTIF]\t CBTNotifierBase::ChangeAuthorizeState()"));   
    TBTDeviceSecurity sec = iDevice->GlobalSecurity();
    sec.SetBanned(EFalse);
    sec.SetNoAuthorise( ( aTrust ) ? ETrue : EFalse ) ;
    iDevice->SetGlobalSecurity(sec);
 
    iBTRegistryQueryState = ESetDeviceAuthorizeState;
    if( !iDevMan )
        {
        iDevMan = CBTEngDevMan::NewL( this );    
        }
    TInt devManErr = iDevMan->ModifyDevice( *iDevice );     
            
    // if error, complete message, otherwise waiting for devman callback
    //
    if(devManErr != KErrNone)
        {
        CompleteMessage(devManErr); 
        TBTNotifLockPublish::DeleteNotifLocks( 
                EBTNotiferLockPairedDeviceSetting, iDevice->BDAddr() );
        }
    }

// ----------------------------------------------------------
// CBTNotifierBase::CheckAndHandleQueryIntervalL
// ----------------------------------------------------------
//
void CBTNotifierBase::CheckAndHandleQueryIntervalL()
    {
    FLOG( _L( "[BTNOTIF]\t CBTNotifierBase::CheckQueryInterval start." ) );
    TBool res = CheckQueryInterval();
    if( res )
        {
        FLOG( _L( "[BTNOTIF]\t CBTNotifierBase::CheckQueryInterval check on/off query status." ) );
        // Check if we're already showing Turn BT off query
        TInt queryValue=EBTQueryOff;
        RProperty::Get( KPSUidBluetoothEnginePrivateCategory, KBTTurnBTOffQueryOn, queryValue );
        if( queryValue==EBTQueryOff )
            {
            FLOG( _L( "[BTNOTIF]\t CBTNotifierBase::CheckQueryInterval asking to turn BT off." ) );
            RProperty::Set( KPSUidBluetoothEnginePrivateCategory, KBTTurnBTOffQueryOn, EBTQueryOn );
            TInt keypress = iNotifUiUtil->ShowQueryL( KErrNone, R_BT_TURN_BT_OFF_NOTE, ECmdBTnotifUnavailable );
            RProperty::Set( KPSUidBluetoothEnginePrivateCategory, KBTTurnBTOffQueryOn, EBTQueryOff );
            if( keypress )  // User has accepted the dialog
                {
                FLOG( _L( "[BTNOTIF]\t CBTNotifierBase::CheckQueryInterval turning BT off." ) );
                (void) iBTEngSettings->SetPowerState( EBTPowerOff );
                CompleteMessage( KErrAccessDenied );
                }
            }
        }
    FLOG( _L( "[BTNOTIF]\t CBTNotifierBase::CheckAndHandleQueryIntervalL done." ) );
    }

void CBTNotifierBase::DoHandleGetDevicesCompleteL( TInt aErr, CBTDeviceArray* aDeviceArray)
    {
    FTRACE(FPrint(_L("[BTNOTIF]\t CBTNotifierBase::DoHandleGetDevicesCompleteL(%d)"), aErr ));
    TBTDeviceName devName;
    if (!aErr && aDeviceArray && aDeviceArray->Count())
        {
        // Reassign so that we won't lose the device name as it is
        // needed if registry doesn't have the name for this device yet:
        CBTDevice* temp = iDevice;
        CleanupStack::PushL(temp);
        // Taking the object returned by registry so that iDevice have
        // all the up-to-date information except device name.
        iDevice = aDeviceArray->At(0);
        aDeviceArray->Delete( 0 );
        // we show user the device name from registry if it is available;
        // Otherwise, the name passed in by the notifier request shall be 
        // used.
        if( ( !iDevice->IsValidDeviceName() || 
              !iDevice->DeviceName().Length() ) && 
            temp->IsValidDeviceName() )
            {
            // We are using a stored device name, which will
            // already have been processed
            iDevice->SetDeviceNameL( temp->DeviceName() );
            }
        CleanupStack::PopAndDestroy(temp);
        }
    BtNotifNameUtils::GetDeviceName(devName, iDevice);   
    
    // It is possible that iDevice hasn't got a name so far. Use the default BT name
    // got from GetDeviceName().
    if ( !iDevice->IsValidDeviceName() || !iDevice->DeviceName().Length() )
        {
        BtNotifNameUtils::SetDeviceNameL(devName, *iDevice);
        }
    HandleGetDeviceCompletedL( iDevice ); 
    }

// ----------------------------------------------------------
// CBTNotifierBase::CompleteMessage
// ----------------------------------------------------------
//	
void CBTNotifierBase::CompleteMessage(TInt aErr)
    {	   
	if( !iMessage.IsNull() )
	    {
	    FTRACE(FPrint(_L("[BTNOTIF]\t CBTNotifierBase::CompleteMessage(%d)"), aErr ));
	    iMessage.Complete( aErr );
	    }
	}

// ----------------------------------------------------------
// CBTNotifierBase::CompleteMessage
// ----------------------------------------------------------
//	
void CBTNotifierBase::CompleteMessage(TInt aValueToReplySlot, TInt aErr)
    {
    FTRACE(FPrint(_L("[BTNOTIF]\t CBTNotifierBase::CompleteMessage(%d, %d)"), 
            aValueToReplySlot, aErr ) );
    CompleteMessage(TPckgBuf<TInt>( aValueToReplySlot ), aErr);
	}

// ----------------------------------------------------------
// CBTNotifierBase::CompleteMessage
// ----------------------------------------------------------
//	
void CBTNotifierBase::CompleteMessage(const TDesC8& aDesToReplySlot, TInt aErr)
    {	   
	if( !iMessage.IsNull() )
	    {
	    FTRACE(FPrint(_L("[BTNOTIF]\t CBTNotifierBase::CompleteMessage(TDesC8&, %d)"), aErr ) );
	    if ( !aErr )
	        {
	        aErr = iMessage.Write( iReplySlot, aDesToReplySlot );
	        }
	    iMessage.Complete( aErr );
	    }
	}

#ifdef __SERIES60_HELP    
//-------------------------------------------------------------
// CBTNotifierBase::LaunchHelp
//--------------------------------------------------------------
TInt CBTNotifierBase::LaunchHelp(TAny * tCoeHelpContext )
	{	
	TCoeHelpContext hc;
	
	if( tCoeHelpContext==NULL)
		hc = TCoeHelpContext(KUidBTUI,KBT_HLP_BLOCKED);
	else
		hc = *static_cast<TCoeHelpContext*>(tCoeHelpContext);
		 
		CArrayFix< TCoeHelpContext >* array = new CArrayFixFlat< TCoeHelpContext >(1);
	TRAPD(err,
		{
		CleanupStack::PushL(array);
		array->AppendL(hc);		
		HlpLauncher::LaunchHelpApplicationL( CCoeEnv::Static()->WsSession() , array );
    	CleanupStack::Pop(array);
		});

    // the array is not deleted, since deleting it will result
    // to E32User-CBase 3. It is assumed that HlpLancher is taking care of it.
    // however this has not been documented.
    return err;
	}
#endif

void CBTNotifierBase::HandleGetDevicesComplete( TInt aErr, CBTDeviceArray* aDeviceArray)
    {
    TRAP_IGNORE(DoHandleGetDevicesCompleteL(aErr, aDeviceArray));
    }

void CBTNotifierBase::HandleDevManComplete(TInt aErr)
    {
    FTRACE(FPrint(_L("[BTNOTIF]\t CBTNotifierBase::HandleDevManComplete()  aErr = %d"), aErr ));
    
    switch (iBTRegistryQueryState)
        {
        case ESetDeviceBlocked:
            {
            // Blocking device was demanded by user after the user
            // rejected incoming pairing or connect request. The message
            // to be completed here is the original pair or authorization request
            // which has been rejected by the user.
            CompleteMessage(KErrCancel);
            }
        case ESetDeviceAuthorizeState:
            {
            TBTNotifLockPublish::DeleteNotifLocks( 
                    EBTNotiferLockPairedDeviceSetting, iDevice->BDAddr() );
            CompleteMessage(aErr);
            break;
            }
        }
    FLOG(_L("[BTNOTIF]\t CBTNotifierBase::HandleDevManComplete() Complete"));           
    }

void CBTNotifierBase::HandleGetDeviceCompletedL(const CBTDevice* /*aDev*/)
    {    
    }

// ----------------------------------------------------------
// CBTNotifierBase::CheckQueryInterval
// ----------------------------------------------------------
//
TBool CBTNotifierBase::CheckQueryInterval()
    {
    FLOG( _L( "[BTNOTIF]\t CBTNotifierBase::CheckQueryInterval()" ) );
    TBool result = EFalse;
    // Check if the user gets too many queries within a certain time interval from unpaired devices
    if( iDevice && !iDevice->IsValidLinkKey() )
        {
        TBuf8<32> buf;
        TTime now;
        now.UniversalTime();    // Get current time
        TInt64 writeTime = ( now + REJECT_ADD_TIME ).Int64();

        // get last connection time
        TInt err = RProperty::Get( KPSUidBluetoothEnginePrivateCategory, KBTConnectionTimeStamp, buf );
        if( !err )
            {
            FLOG( _L( "[BTNOTIF]\t CBTNotifierBase::CheckQueryInterval Checking query interval." ) );
            // Parse recorded time stamp
            TInt64 num(0);
            TLex8 lex;
            lex = buf;
            lex.Val( num );
            TTime lastTime( num );

            // detection of clock adjusment
            TInt timetravel = 2 * REJECT_ADD_TIME.Int();
            if( lastTime > now + TTimeIntervalSeconds(timetravel) )
                {
                FLOG( _L( "[BTNOTIF]\t CBTNotifierBase::CheckQueryInterval  time travel detection." ) );
                lastTime = now;
                }
            // new request too quickly, move booked time
            if( lastTime + CONNECT_ADD_TIME > now )
                {
                FLOG( _L( "[BTNOTIF]\t CBTAuthNotifier::IsDosAttack  CONNECT_ADD_TIME added." ) );
                writeTime = ( lastTime + CONNECT_ADD_TIME ).Int64();
                }

            FTRACE( FPrint( _L( "[BTNOTIF]\t CBTNotifierBase::CheckQueryInterval() lastTime = %d" ), lastTime.Int64() ) );
            FTRACE( FPrint( _L( "[BTNOTIF]\t CBTNotifierBase::CheckQueryInterval now + treshold: %d" ), (now + DENY_THRESHOLD).Int64() ) );
            // If threshold is exceeded, ask user to turn Bluetooth OFF
            if( lastTime > now + DENY_THRESHOLD )
                {
                FLOG( _L( "[BTNOTIF]\t CBTNotifierBase::CheckQueryInterval threshold exceeded!." ) );
                result = ETrue;
                }
            }
        else
            {
            FLOG( _L( "[BTNOTIF]\t CBTNotifierBase::CheckQueryInterval setting connection timestamp first time." ) );
            }
        // Write back the timestamp
        buf.Num( writeTime );
        FTRACE( FPrint( _L( "[BTNOTIF]\t CBTNotifierBase::CheckQueryInterval updating timestamp: %d." ), writeTime ) );
        RProperty::Set( KPSUidBluetoothEnginePrivateCategory,KBTConnectionTimeStamp, buf );
        } // end of query interval check
    FLOG( _L( "[BTNOTIF]\t CBTNotifierBase::CheckQueryInterval() complete" ) );
    return result;
    }
// End of File