mmserv/sts/stsproxy/src/rstssession.cpp
changeset 20 b67dd1fc57c5
child 36 73253677b50a
equal deleted inserted replaced
19:4a629bc82c5e 20:b67dd1fc57c5
       
     1 /*
       
     2  * Copyright (c) 2010 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:
       
    15  * The file provides the implementation of the client side session
       
    16  * to the STS Server.
       
    17  */
       
    18 
       
    19 #include "rstssession.h"
       
    20 #include "stsclientservercommon.h"
       
    21 
       
    22 const TUint KNumSlots = 30;
       
    23 
       
    24 /*static*/TInt RStsSession::CallBackThreadMain(TAny* aSession)
       
    25     {
       
    26     TInt err = KErrNoMemory;
       
    27 
       
    28     RThread myThread;
       
    29     myThread.SetPriority(EPriorityAbsoluteHigh);
       
    30     myThread.Close();
       
    31 
       
    32     CTrapCleanup* cleanup = CTrapCleanup::New();
       
    33 
       
    34     if (cleanup)
       
    35         {
       
    36         // Run the server and request a thread rendezvous.
       
    37         TRAP( err, ((RStsSession*)aSession)->RunThreadL() );
       
    38         delete cleanup;
       
    39         }
       
    40 
       
    41     return err;
       
    42     }
       
    43 
       
    44 void RStsSession::RunThreadL()
       
    45     {
       
    46     iState = ERunning;
       
    47     // Initialisation complete, now signal the client, if requested.
       
    48     RThread::Rendezvous(KErrNone);
       
    49     TRequestStatus queueStatus = KRequestPending;
       
    50     iMsgQueue.NotifyDataAvailable(queueStatus);
       
    51 
       
    52     RThread server;
       
    53     TInt err = server.Open(iServerThreadId);
       
    54     TRequestStatus serverStatus = KRequestPending;
       
    55     server.Logon(serverStatus);
       
    56 
       
    57     while (iState == ERunning)
       
    58         {
       
    59         TStsCallBack message;
       
    60         // Using ReceiveBlocking here would block forever if the executive thread
       
    61         // dies, so instead wait for either a data available notification or a
       
    62         // notification that the executive thread has died.
       
    63         User::WaitForRequest(queueStatus, serverStatus);
       
    64 
       
    65         if (queueStatus != KRequestPending)
       
    66             {
       
    67             TInt err = iMsgQueue.Receive(message);
       
    68             if (err == KErrNone)
       
    69                 {
       
    70                 HandleMessage(message);
       
    71                 }
       
    72             else
       
    73                 {
       
    74                 //TODO:Log a message
       
    75                 }
       
    76             queueStatus = KRequestPending;
       
    77             iMsgQueue.NotifyDataAvailable(queueStatus);
       
    78             }
       
    79         if (serverStatus != KRequestPending && iState == ERunning)
       
    80             {
       
    81             //TODO: Log a message
       
    82             //Restart the server
       
    83             SignalObservers();
       
    84             server.Close();
       
    85             CreateServerSession();
       
    86             TInt err = server.Open(iServerThreadId);
       
    87             TRequestStatus serverStatus = KRequestPending;
       
    88             server.Logon(serverStatus);
       
    89             }
       
    90         }
       
    91 
       
    92     iMsgQueue.CancelDataAvailable();
       
    93     server.LogonCancel(serverStatus);
       
    94     server.Close();
       
    95     }
       
    96 
       
    97 void RStsSession::HandleMessage(TStsCallBack& aMessage)
       
    98     {
       
    99     TStsCallBackType type = aMessage.callBackType;
       
   100     if (type == EStsPlayAlarmComplete)
       
   101         {
       
   102         MStsPlayAlarmObserver* observer = aMessage.observer;
       
   103         unsigned int context = aMessage.alarmContext;
       
   104         iObserverMutex.Wait();
       
   105         if (observer == iObserverMap[context])
       
   106             {
       
   107             observer->PlayAlarmComplete(aMessage.alarmContext);
       
   108             }
       
   109         else
       
   110             {
       
   111             //TODO: Log a message
       
   112             }
       
   113         iObserverMap.erase(context);
       
   114         iObserverMutex.Signal();
       
   115         }
       
   116     else if (type == EStsShutdown)
       
   117         {
       
   118         iState = EStopping;
       
   119         }
       
   120     else
       
   121         {
       
   122         //TODO: Log error message
       
   123         }
       
   124     }
       
   125 
       
   126 TInt RStsSession::StartServer()
       
   127     {
       
   128     TInt err = KErrNone;
       
   129 
       
   130     // Launch the server executable (i.e. in it its own process).
       
   131 
       
   132     // Create a new server process. Simultaneous launching of two such processes 
       
   133     // should be detected when the second one attempts to create the server 
       
   134     // object, failing with KErrAlreadyExists.
       
   135     RProcess server;
       
   136     err = server.Create(KStsServerFile, KNullDesC);
       
   137 
       
   138     if (err == KErrNone)
       
   139         {
       
   140         TRequestStatus rendezvousStatus;
       
   141         server.Rendezvous(rendezvousStatus);
       
   142         server.Resume();
       
   143 
       
   144         // wait for start or death
       
   145         User::WaitForRequest(rendezvousStatus);
       
   146 
       
   147         // we can't use the 'exit reason' if the server panicked as this
       
   148         // is the panic 'reason' and may be '0' which cannot be distinguished
       
   149         // from KErrNone  
       
   150         if (server.ExitType() == EExitPanic)
       
   151             {
       
   152             err = KErrGeneral;
       
   153             }
       
   154         else
       
   155             {
       
   156             err = rendezvousStatus.Int();
       
   157             }
       
   158         }
       
   159     server.Close();
       
   160 
       
   161     return err;
       
   162     }
       
   163 
       
   164 TInt RStsSession::StartThread()
       
   165     {
       
   166     TInt result = iThread.Create(KNullDesC, RStsSession::CallBackThreadMain,
       
   167             KDefaultStackSize, &User::Heap(), (TAny*) this);
       
   168 
       
   169     if (result == KErrNone)
       
   170         {
       
   171         TRequestStatus rendezvousStatus = KRequestPending;
       
   172 
       
   173         //  Register for rendezvous notification when thread is started.
       
   174         iThread.Rendezvous(rendezvousStatus);
       
   175 
       
   176         // Start the thread execution
       
   177         iThread.Resume();
       
   178 
       
   179         // Wait for thread to start.
       
   180         User::WaitForRequest(rendezvousStatus);
       
   181 
       
   182         result = rendezvousStatus.Int();
       
   183 
       
   184         if (result != KErrNone)
       
   185             {
       
   186             iThread.Kill(result);
       
   187             }
       
   188         }
       
   189 
       
   190     return result;
       
   191     }
       
   192 
       
   193 TInt RStsSession::CreateServerSession()
       
   194     {
       
   195     // Try to create a session with the server
       
   196     TInt result = CreateSession(KStsServerName, TVersion(
       
   197             KStsServerMajorVersion, KStsServerMinorVersion, KStsServerBuild),
       
   198             KNumSlots, EIpcSession_Sharable);
       
   199 
       
   200     // If the server wasn't found, start the server and try creating a session again
       
   201     if (result == KErrNotFound || result == KErrServerTerminated)
       
   202         {
       
   203         result = StartServer();
       
   204         if (result == KErrNone || result == KErrAlreadyExists)
       
   205             {
       
   206             result = CreateSession(KStsServerName, TVersion(
       
   207                     KStsServerMajorVersion, KStsServerMinorVersion,
       
   208                     KStsServerBuild), KNumSlots, EIpcSession_Sharable);
       
   209             }
       
   210         }
       
   211 
       
   212     if (result == KErrNone)
       
   213         {
       
   214         TPckg<TThreadId> idPckg(iServerThreadId);
       
   215         result = SendReceive(StsMsg_RegisterMsgQueue, TIpcArgs(iMsgQueue,
       
   216                 &idPckg));
       
   217         }
       
   218 
       
   219     return result;
       
   220     }
       
   221 
       
   222 TInt RStsSession::Connect()
       
   223     {
       
   224     iState = EInitializing;
       
   225 
       
   226     // Create a nameless global message queue, then pass the handle to the queue to the server.
       
   227     TInt result = iMsgQueue.CreateGlobal(KNullDesC, 30);
       
   228 
       
   229     // Create thread for receiving asynch callbacks from the server
       
   230     if (result == KErrNone)
       
   231         {
       
   232         result = CreateServerSession();
       
   233         if (result == KErrNone)
       
   234             {
       
   235             result = StartThread();
       
   236             if (result == KErrNone)
       
   237                 {
       
   238                 result = iObserverMutex.CreateLocal();
       
   239                 }
       
   240             }
       
   241         }
       
   242 
       
   243     return result;
       
   244     }
       
   245 
       
   246 void RStsSession::Close()
       
   247     {
       
   248     TRequestStatus logonStatus = KRequestPending;
       
   249     iThread.Logon(logonStatus);
       
   250     RSessionBase::Close();
       
   251     User::WaitForRequest(logonStatus);
       
   252     iThread.Close();
       
   253     iMsgQueue.Close();
       
   254     CleanUpObservers();
       
   255     iObserverMutex.Close();
       
   256     }
       
   257 
       
   258 void RStsSession::SendPlayTone(CSystemToneService::TToneType aTone)
       
   259     {
       
   260     TInt err = SendReceive(StsMsg_PlayTone, TIpcArgs(aTone));
       
   261     if (err != KErrNone)
       
   262         {
       
   263         //TODO: Log a message
       
   264         }
       
   265     }
       
   266 
       
   267 void RStsSession::SendPlayAlarm(CSystemToneService::TAlarmType aAlarm,
       
   268         unsigned int& aAlarmContext, MStsPlayAlarmObserver& aObserver)
       
   269     {
       
   270     TPckg<unsigned int> alarmContextPckg(aAlarmContext);
       
   271     TInt err = SendReceive(StsMsg_PlayAlarm, TIpcArgs(aAlarm,
       
   272             &alarmContextPckg, &aObserver));
       
   273     if (err != KErrNone)
       
   274         {
       
   275         //TODO: Log a message
       
   276         aObserver.PlayAlarmComplete(aAlarmContext);
       
   277         }
       
   278     else
       
   279         {
       
   280         iObserverMutex.Wait();
       
   281         iObserverMap[aAlarmContext] = &aObserver;
       
   282         iObserverMutex.Signal();
       
   283         }
       
   284     }
       
   285 
       
   286 void RStsSession::SendStopAlarm(unsigned int aAlarmContext)
       
   287     {
       
   288     iObserverMutex.Wait();
       
   289     iObserverMap.erase(aAlarmContext);
       
   290     iObserverMutex.Signal();
       
   291     TInt err = SendReceive(StsMsg_StopAlarm, TIpcArgs(aAlarmContext));
       
   292     if (err != KErrNone)
       
   293         {
       
   294         //TODO: Log a message
       
   295         }
       
   296     }
       
   297 
       
   298 void RStsSession::CleanUpObservers()
       
   299     {
       
   300     iObserverMutex.Wait();
       
   301     while (!iObserverMap.empty())
       
   302         {
       
   303         //TODO: Add trace here
       
   304         unsigned int context = iObserverMap.begin()->first;
       
   305         iObserverMap.erase(context);
       
   306         }
       
   307     iObserverMutex.Signal();
       
   308     }
       
   309 
       
   310 void RStsSession::SignalObservers()
       
   311     {
       
   312     iObserverMutex.Wait();
       
   313     while (!iObserverMap.empty())
       
   314         {
       
   315         //TODO: Add trace here
       
   316         unsigned int context = iObserverMap.begin()->first;
       
   317         iObserverMap[context]->PlayAlarmComplete(context);
       
   318         iObserverMap.erase(context);
       
   319         }
       
   320     iObserverMutex.Signal();
       
   321     }