bluetoothengine/btaudioman/src/basrvaccstateattached.cpp
changeset 0 f63038272f30
child 6 6a29d5ad0713
equal deleted inserted replaced
-1:000000000000 0:f63038272f30
       
     1 /*
       
     2 * Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementation of Connected state.
       
    15 *  Version     : %version: 20 %
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include <e32property.h>
       
    22 #include <ctsydomainpskeys.h>
       
    23 #include "basrvaccstateattached.h"
       
    24 #include "basrvaccstateattach.h"
       
    25 #include "basrvaccstatedetach.h"
       
    26 #include "basrvaccstatedisconnect.h"
       
    27 #include "BTAccInfo.h"
       
    28 #include "debug.h"
       
    29 
       
    30 const TInt KRequestIdOpenMonoAudio = 40;
       
    31 const TInt KRequestIdOpenStereoAudio = 41;
       
    32 const TInt KRequestIdCloseMonoAudio = 42;
       
    33 const TInt KRequestIdCloseStereoAudio = 43;
       
    34 const TInt KRequestIdTimer = 44;
       
    35 const TInt KRequestIdMonoActiveModeRequest = 45;
       
    36 const TInt KRequestIdStereoActiveModeRequest = 46;
       
    37 const TInt KRequestIdConnectRemConTG = 47;
       
    38 
       
    39 const TInt KAudioCloseResponseDelay = 1200000; // 1.2 sec
       
    40 
       
    41 // ================= MEMBER FUNCTIONS =======================
       
    42 
       
    43 CBasrvAccStateAttached* CBasrvAccStateAttached::NewL(CBasrvAcc& aParent, TBool aShowNote)
       
    44     {
       
    45     CBasrvAccStateAttached* self=new(ELeave) CBasrvAccStateAttached(aParent, aShowNote);
       
    46     return self;
       
    47     }
       
    48 
       
    49 CBasrvAccStateAttached::~CBasrvAccStateAttached()
       
    50     {
       
    51     delete iRemConTGConnector;
       
    52     delete iAudioOpener;
       
    53     delete iAudioCloser;
       
    54     delete iTimerActive;
       
    55     iTimer.Close();
       
    56     TRACE_FUNC
       
    57     }
       
    58 
       
    59 void CBasrvAccStateAttached::EnterL()
       
    60     {
       
    61     StatePrint(_L("Attached"));
       
    62     iTimer.CreateLocal();
       
    63     if (AccInfo().iAudioOpenedProfiles)
       
    64         {
       
    65         if (AccInfo().iAudioOpenedProfiles & EStereo)
       
    66             HandleAccOpenedAudio(EStereo);
       
    67         if (AccInfo().iAudioOpenedProfiles & EHFP)
       
    68             HandleAccOpenedAudio(EHFP);
       
    69         if (AccInfo().iAudioOpenedProfiles & EHSP)
       
    70             HandleAccOpenedAudio(EHSP);
       
    71         }
       
    72     else
       
    73         {
       
    74         Parent().RequestSniffMode();
       
    75         }
       
    76     if (iShowNote)
       
    77         {
       
    78         Parent().AccMan().NotifyClientNewProfile(AccInfo().iConnProfiles, AccInfo().iAddr);
       
    79         TInt callState;
       
    80         TInt err = RProperty::Get(KPSUidCtsyCallInformation, KCTsyCallState, callState);
       
    81         if(!err && (callState == EPSCTsyCallStateNone || callState == EPSCTsyCallStateUninitialized))
       
    82             {
       
    83 		    Parent().AccMan().ShowNote(EBTConnected, AccInfo().iAddr); 				  		
       
    84             }
       
    85         }
       
    86     }
       
    87 
       
    88 CBasrvAccState* CBasrvAccStateAttached::ErrorOnEntry(TInt /*aReason*/)
       
    89     {
       
    90     TRACE_FUNC
       
    91     CBasrvAccState* next = NULL;
       
    92     TRAP_IGNORE(next = CBasrvAccStateDetach::NewL(Parent()));
       
    93     return next;
       
    94     }
       
    95 
       
    96 TBTEngConnectionStatus CBasrvAccStateAttached::ConnectionStatus() const
       
    97     {
       
    98     return EBTEngConnected;
       
    99     }
       
   100 
       
   101 void CBasrvAccStateAttached::ConnectL(const TBTDevAddr& aAddr)
       
   102     {
       
   103     if (aAddr == AccInfo().iAddr)
       
   104         {
       
   105         Parent().AccMan().ConnectCompletedL(AccInfo().iAddr, KErrNone, AccInfo().iConnProfiles);
       
   106         }
       
   107     else
       
   108         {
       
   109         CBasrvAccState::ConnectL(aAddr);
       
   110         }
       
   111     }
       
   112 
       
   113 void CBasrvAccStateAttached::DisconnectL()
       
   114     {
       
   115     TRACE_FUNC
       
   116     Parent().AccMan().RemoveAudioRequest(AccInfo().iAddr);
       
   117         
       
   118     if (AccInfo().iAudioOpenedProfiles)
       
   119         {
       
   120         TAccAudioType type = (AccInfo().iAudioOpenedProfiles & EAnyMonoAudioProfiles) 
       
   121                 ? EAccMonoAudio : EAccStereoAudio;    
       
   122         Parent().AccMan().AccfwConnectionL()->NotifyAudioLinkCloseL(AccInfo().iAddr, type);
       
   123         AccInfo().iAudioOpenedProfiles = EUnknownProfile;
       
   124         }
       
   125     
       
   126     Parent().ChangeStateL(CBasrvAccStateDetach::NewL(Parent()));
       
   127     }
       
   128 
       
   129 void CBasrvAccStateAttached::AccessoryConnected(TProfiles aProfile)
       
   130     {
       
   131     TRACE_FUNC
       
   132     CBasrvAccState::AccessoryConnected(aProfile);
       
   133     Parent().NotifyLinkChange2Rvc();
       
   134     Parent().AccMan().NotifyClientNewProfile(aProfile, AccInfo().iAddr);
       
   135     }
       
   136 
       
   137 void CBasrvAccStateAttached::AccOpenedAudio(TProfiles aProfile)
       
   138     {
       
   139     TRACE_FUNC
       
   140     delete iTimerActive;
       
   141     iTimerActive = NULL;    
       
   142     HandleAccOpenedAudio(aProfile);
       
   143     }
       
   144 
       
   145 void CBasrvAccStateAttached::AccClosedAudio(TProfiles aProfile)
       
   146     {
       
   147     TRACE_FUNC
       
   148     UpdateAudioState(EAudioLinkClosed, (aProfile == EStereo) ? EAccStereoAudio : EAccMonoAudio);
       
   149     CBasrvAccState::AccClosedAudio(aProfile);
       
   150     Parent().NotifyLinkChange2Rvc();
       
   151     iCloseAudioProfile = aProfile;
       
   152     if (!iTimerActive)
       
   153         {
       
   154         iTimerActive = CBasrvActive::New(*this, CActive::EPriorityStandard, KRequestIdTimer);
       
   155         }
       
   156     if (iTimerActive)
       
   157         {
       
   158         iTimerActive->Cancel();
       
   159         iTimer.After(iTimerActive->iStatus, KAudioCloseResponseDelay);
       
   160         iTimerActive->GoActive();
       
   161         }
       
   162     Parent().RequestSniffMode();
       
   163     StatePrint(_L("Attached"));    
       
   164     }
       
   165 
       
   166 void CBasrvAccStateAttached::AccessoryDisconnectedL(TProfiles aProfile)
       
   167     {
       
   168     TRACE_FUNC
       
   169     delete iTimerActive;
       
   170     iTimerActive = NULL;
       
   171     TInt audiolinkcache = AccInfo().iAudioOpenedProfiles;
       
   172     if ((AccInfo().iAudioOpenedProfiles & EStereo) && (aProfile & EStereo))
       
   173         {
       
   174         Parent().RequestSniffMode();
       
   175         }
       
   176     ProfileDisconnected(aProfile);
       
   177     CBasrvAccState::AccClosedAudio(aProfile);
       
   178     Parent().NotifyLinkChange2Rvc();
       
   179     Parent().AccMan().NotifyClientNoProfile(aProfile, AccInfo().iAddr);
       
   180     StatePrint(_L("Attached"));
       
   181 
       
   182     // AudioPolicy wants to get a notification about audio link closes before
       
   183     // detaches as well so here we go
       
   184     if (audiolinkcache & aProfile ||
       
   185         iCloseAudioProfile & aProfile )
       
   186         {
       
   187         TAccAudioType type = (aProfile & EAnyMonoAudioProfiles) 
       
   188             ? EAccMonoAudio : EAccStereoAudio;
       
   189         Parent().AccMan().AccfwConnectionL()->NotifyAudioLinkCloseL(AccInfo().iAddr, type);    
       
   190         
       
   191         // let's clear this variable here to be sure it's not used twice accidentally
       
   192         iCloseAudioProfile = EUnknownProfile;
       
   193         }
       
   194 
       
   195     if (!(AccInfo().iConnProfiles & EAnyAudioProfiles))
       
   196         {
       
   197         Parent().AccMan().RemoveAudioRequest(AccInfo().iAddr);
       
   198         Parent().ChangeStateL(CBasrvAccStateDetach::NewL(Parent()));
       
   199         }
       
   200 
       
   201     }
       
   202 
       
   203 void CBasrvAccStateAttached::OpenAudioL(TAccAudioType aType)
       
   204     {
       
   205     TRACE_FUNC
       
   206     TInt requestId = (aType == EAccMonoAudio) 
       
   207         ? KRequestIdMonoActiveModeRequest : KRequestIdStereoActiveModeRequest;
       
   208     if (!iAudioOpener)
       
   209         {
       
   210         iAudioOpener = CBasrvActive::NewL(*this, CActive::EPriorityLow, requestId);
       
   211         }
       
   212     else
       
   213         {
       
   214         if (iAudioOpener->IsActive())
       
   215             {
       
   216             LEAVE(KErrAlreadyExists);
       
   217             }
       
   218         iAudioOpener->SetRequestId(requestId);
       
   219         }
       
   220     Parent().RequestActiveMode();
       
   221 
       
   222 	// here we'll give time to the scheduler so that the active mode request has 
       
   223 	// a chance to get through before the audio link open request - running
       
   224 	// with EPriorityLow for that
       
   225 	TRequestStatus* myStatus( &iAudioOpener->iStatus );
       
   226     *myStatus = KRequestPending;
       
   227     iAudioOpener->GoActive();
       
   228 	User::RequestComplete( myStatus, KErrNone );
       
   229     }
       
   230 
       
   231 void CBasrvAccStateAttached::CloseAudioL(TAccAudioType aType)
       
   232     {
       
   233     TRACE_FUNC
       
   234 
       
   235     DoCloseAudioL(aType);
       
   236     }
       
   237 
       
   238 void CBasrvAccStateAttached::RequestCompletedL(CBasrvActive& aActive)
       
   239     {
       
   240     TRACE_FUNC
       
   241     TInt status = aActive.iStatus.Int();
       
   242     TInt requestid = aActive.RequestId(); 
       
   243     switch (requestid)
       
   244         {
       
   245         case KRequestIdOpenMonoAudio:
       
   246             {
       
   247             if (!status)
       
   248                 {
       
   249                 if (AccInfo().iSuppProfiles & EHFP)
       
   250                     NewProfileConnection(EHFP);
       
   251                 else
       
   252                     NewProfileConnection(EHSP);
       
   253                 }
       
   254             TInt err = Parent().AccMan().OpenAudioCompleted(AccInfo().iAddr, EAccMonoAudio, status);
       
   255             if ( (err && err != KErrAlreadyExists) || (status && status != KErrInUse && status != KErrAlreadyExists))
       
   256                 {
       
   257                 if (Parent().AccMan().DisconnectIfAudioOpenFails())
       
   258                     {
       
   259                     Parent().AccMan().RemoveAudioRequest(AccInfo().iAddr);
       
   260                     Parent().ChangeStateL(CBasrvAccStateDetach::NewL(Parent()));
       
   261                     }
       
   262                 }
       
   263             else
       
   264                 {
       
   265                 UpdateAudioState(EAudioLinkOpen, EAccMonoAudio);
       
   266                 Parent().CancelPowerModeControl();
       
   267                 AccInfo().iAudioOpenedProfiles |= (AccInfo().iConnProfiles & EAnyMonoAudioProfiles);
       
   268                 Parent().NotifyLinkChange2Rvc();
       
   269                 }
       
   270             break;
       
   271             }
       
   272         case KRequestIdCloseMonoAudio:
       
   273             {
       
   274             UpdateAudioState(EAudioLinkClosed, EAccMonoAudio);
       
   275             Parent().RequestSniffMode();
       
   276             (void) Parent().AccMan().CloseAudioCompleted(AccInfo().iAddr, EAccMonoAudio, status);
       
   277             break;
       
   278             }
       
   279         case KRequestIdOpenStereoAudio:
       
   280             {
       
   281             if (!status)
       
   282                 {
       
   283                 NewProfileConnection(EStereo);              
       
   284                 }
       
   285             TInt err = Parent().AccMan().OpenAudioCompleted(AccInfo().iAddr, EAccStereoAudio, status);
       
   286             if ((status && status != KErrInUse && status != KErrAlreadyExists))
       
   287                 {
       
   288                 if (status == KErrDisconnected)
       
   289                     {
       
   290                     ProfileDisconnected(EStereo);
       
   291                     }
       
   292                 if (Parent().AccMan().DisconnectIfAudioOpenFails())
       
   293                     {
       
   294                     Parent().AccMan().RemoveAudioRequest(AccInfo().iAddr);
       
   295                     Parent().ChangeStateL(CBasrvAccStateDetach::NewL(Parent()));
       
   296                     }
       
   297                 }
       
   298             else if (!err)
       
   299                 {
       
   300                 UpdateAudioState(EAudioLinkOpen, EAccStereoAudio);
       
   301                 Parent().PreventLowPowerMode();
       
   302                 AccInfo().iAudioOpenedProfiles |= EStereo;
       
   303                 Parent().NotifyLinkChange2Rvc();
       
   304                 DoConnectRemConCtIfNeededL();
       
   305                 }
       
   306             break;
       
   307             }
       
   308         case KRequestIdCloseStereoAudio:
       
   309             {
       
   310             UpdateAudioState(EAudioLinkClosed, EAccStereoAudio);
       
   311             Parent().RequestSniffMode();
       
   312             (void) Parent().AccMan().CloseAudioCompleted(AccInfo().iAddr, EAccStereoAudio, status);
       
   313             break;
       
   314             }
       
   315         case KRequestIdTimer:
       
   316             {
       
   317             TAccAudioType type = (iCloseAudioProfile & EAnyMonoAudioProfiles) 
       
   318                 ? EAccMonoAudio : EAccStereoAudio;
       
   319             Parent().AccMan().AccfwConnectionL()->NotifyAudioLinkCloseL(AccInfo().iAddr, type);    
       
   320 
       
   321             // this variable needs to be cleared here so that the AccFW isn't notified a second time
       
   322             // about the same audio link close during disconnection process
       
   323             iCloseAudioProfile = EUnknownProfile;
       
   324             break;
       
   325             }
       
   326         case KRequestIdMonoActiveModeRequest:
       
   327         case KRequestIdStereoActiveModeRequest:
       
   328             {
       
   329             // the active mode request should have been scheduled at this point and we'll continue
       
   330             // with audio link open request - going back to standard priority
       
   331     		TProfiles profile = ( requestid == KRequestIdMonoActiveModeRequest ) ? EHFP : EStereo;            
       
   332 		    Parent().AccMan().PluginMan().Plugin(profile)->OpenAudioLink(AccInfo().iAddr, 
       
   333 		        iAudioOpener->iStatus);
       
   334 
       
   335     		TInt requestId = ( requestid == KRequestIdMonoActiveModeRequest ) 
       
   336     							? KRequestIdOpenMonoAudio : KRequestIdOpenStereoAudio;
       
   337 		    iAudioOpener->SetPriority( CActive::EPriorityStandard );
       
   338 		    iAudioOpener->SetRequestId( requestId );
       
   339 		    iAudioOpener->GoActive();
       
   340             break;
       
   341             }
       
   342         case KRequestIdConnectRemConTG:
       
   343             {
       
   344             if (!status || status == KErrAlreadyExists)
       
   345                 {
       
   346                 NewProfileConnection(ERemConTG);
       
   347                 Parent().NotifyLinkChange2Rvc();
       
   348                 }
       
   349             delete iRemConTGConnector;
       
   350             iRemConTGConnector = NULL;
       
   351             break;
       
   352             }
       
   353         default:
       
   354             {
       
   355             }
       
   356         }
       
   357     }
       
   358     
       
   359 void CBasrvAccStateAttached::CancelRequest(CBasrvActive& aActive)
       
   360     {
       
   361     TRACE_FUNC
       
   362     TInt request = aActive.RequestId();
       
   363     TAccAudioType type = (request == KRequestIdOpenMonoAudio || request == KRequestIdCloseMonoAudio ) ?
       
   364         EAccMonoAudio : EAccStereoAudio;
       
   365     TProfiles profile = (type == EAccMonoAudio) ? EAnyMonoAudioProfiles : EStereo;
       
   366     CBTAccPlugin* plugin = Parent().AccMan().PluginMan().Plugin(profile);
       
   367     if (request == KRequestIdOpenMonoAudio || request == KRequestIdOpenStereoAudio)
       
   368         {
       
   369         plugin->CancelOpenAudioLink(AccInfo().iAddr);
       
   370         Parent().AccMan().OpenAudioCompleted(AccInfo().iAddr, type, KErrCancel);
       
   371         }
       
   372     else if (request == KRequestIdCloseMonoAudio || request == KRequestIdCloseStereoAudio)
       
   373         {
       
   374         plugin->CancelCloseAudioLink(AccInfo().iAddr);
       
   375         Parent().AccMan().CloseAudioCompleted(AccInfo().iAddr, type, KErrCancel);
       
   376         }
       
   377     else if (request == KRequestIdTimer)
       
   378         {
       
   379         iTimer.Cancel();
       
   380         }
       
   381     else if (request == KRequestIdConnectRemConTG)
       
   382         {
       
   383         Parent().AccMan().PluginMan().Plugin(ERemConTG)->CancelConnectToAccessory(AccInfo().iAddr);
       
   384         }
       
   385     }
       
   386 
       
   387 CBasrvAccStateAttached::CBasrvAccStateAttached(CBasrvAcc& aParent, TBool aShowNote)
       
   388     : CBasrvAccState(aParent, NULL), iShowNote(aShowNote)
       
   389     {
       
   390     }
       
   391 
       
   392 void CBasrvAccStateAttached::HandleAccOpenedAudio(TProfiles aProfile)
       
   393     {
       
   394     TRACE_FUNC
       
   395     TAccAudioType type = (aProfile & EAnyMonoAudioProfiles) ? EAccMonoAudio : EAccStereoAudio;
       
   396     TInt latency = Parent().AccMan().PluginMan().AudioLinkLatency(); 
       
   397 
       
   398     TInt ret = Parent().AccMan().NotifyAccFwAudioOpened(AccInfo().iAddr, type, latency);
       
   399 
       
   400 	if (ret == KErrNone)
       
   401         {
       
   402         UpdateAudioState(EAudioLinkOpen, (aProfile == EStereo) ? EAccStereoAudio : EAccMonoAudio);
       
   403         
       
   404         CBasrvAccState::AccOpenedAudio(aProfile);
       
   405         Parent().NotifyLinkChange2Rvc();
       
   406         if (type == EAccStereoAudio)
       
   407             {
       
   408             Parent().RequestActiveMode();
       
   409             Parent().PreventLowPowerMode();
       
   410             Parent().AccMan().PluginMan().Plugin(EStereo)->StartRecording();
       
   411             TRAP_IGNORE(DoConnectRemConCtIfNeededL());
       
   412             }
       
   413         else
       
   414             {
       
   415             Parent().CancelPowerModeControl();
       
   416             }
       
   417         }
       
   418 	
       
   419     StatePrint(_L("Attached"));    
       
   420     }
       
   421     
       
   422 void CBasrvAccStateAttached::DoCloseAudioL(TAccAudioType aType)
       
   423     {
       
   424     TRACE_FUNC
       
   425     TAccAudioType type = (iCloseAudioProfile & EAnyMonoAudioProfiles) ? EAccMonoAudio : EAccStereoAudio;
       
   426     if ( type == aType && iTimerActive  && iTimerActive->IsActive())
       
   427         {
       
   428         TRACE_STATE(_L("[BTAccStateAttached] Timer is cancelled"))   
       
   429         iTimerActive->Cancel();
       
   430         Parent().AccMan().CloseAudioCompleted(AccInfo().iAddr, type, KErrNone);
       
   431         return;
       
   432         }    
       
   433 
       
   434     TInt requestId = (aType == EAccMonoAudio) ? KRequestIdCloseMonoAudio : KRequestIdCloseStereoAudio;
       
   435     if (!iAudioCloser)
       
   436         {
       
   437         iAudioCloser = CBasrvActive::NewL(*this, CActive::EPriorityStandard, requestId);
       
   438         }
       
   439     else
       
   440         {
       
   441         if (iAudioCloser->IsActive())
       
   442             {
       
   443             LEAVE(KErrAlreadyExists);
       
   444             }
       
   445         iAudioCloser->SetRequestId(requestId);
       
   446         }
       
   447     TProfiles profile = (aType == EAccMonoAudio) ? EAnyMonoAudioProfiles : EStereo;
       
   448     AccInfo().iAudioOpenedProfiles &= ~profile;
       
   449     Parent().NotifyLinkChange2Rvc();
       
   450     Parent().AccMan().PluginMan().Plugin(profile)->CloseAudioLink(AccInfo().iAddr, iAudioCloser->iStatus);
       
   451     iAudioCloser->GoActive();
       
   452     }
       
   453 
       
   454 void CBasrvAccStateAttached::DoConnectRemConCtIfNeededL()
       
   455     {
       
   456     TRACE_FUNC
       
   457     if (Parent().AccMan().IsAvrcpVolCTSupported() &&
       
   458         IsAvrcpTGCat2SupportedByRemote() &&
       
   459         !(AccInfo().iConnProfiles & ERemConTG) &&
       
   460         !iRemConTGConnector)
       
   461         {
       
   462         iRemConTGConnector = CBasrvActive::NewL(*this, CActive::EPriorityStandard, KRequestIdConnectRemConTG);
       
   463         CBTAccPlugin* plugin = Parent().AccMan().PluginMan().Plugin(ERemConTG);
       
   464         TRACE_ASSERT(plugin, KErrNotFound)
       
   465         plugin->ConnectToAccessory(AccInfo().iAddr, iRemConTGConnector->iStatus);
       
   466         iRemConTGConnector->GoActive();
       
   467         }
       
   468     }
       
   469 
       
   470 void CBasrvAccStateAttached::UpdateAudioState(TBTAudioLinkState aState, TAccAudioType aType)
       
   471 	{
       
   472 	TBTAudioLinkInfo info;
       
   473 	info.iAddr = AccInfo().iAddr;
       
   474 	info.iProfile = (aType == EAccMonoAudio) ? 0 : 1;
       
   475 	info.iState = aState;
       
   476 	TPckgBuf<TBTAudioLinkInfo> pkg(info);
       
   477 	RProperty::Set(KPSUidBluetoothEnginePrivateCategory, KBTAudioLinkStatus, pkg);
       
   478 	}