uifw/AvKon/akncompamode/srv/src/akncompaserver.cpp
changeset 0 2f259fa3e83a
child 15 c52421ed5f07
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 /*
       
     2 * Copyright (c) 2007 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 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32svr.h>
       
    20 #include <e32uid.h>
       
    21 #include <coemain.h> // CCoeEnv
       
    22 #include <apgtask.h>  // TApaTaskList and friends
       
    23 #include <centralrepository.h>
       
    24 #include <AvkonInternalCRKeys.h>
       
    25 #include <pslninternalcrkeys.h>
       
    26 #include <AknCapServerDefs.h>
       
    27 #include <AknNotifierWrapperDefs.h>
       
    28 
       
    29 #include "akncompasrv.h"
       
    30 #include "akncompaserver.h"
       
    31 
       
    32 // Flags for KAknCompaModeEffects
       
    33 const TInt KAknCompaModeEffectsSaved = (1 << 31);
       
    34 const TInt KAknCompaModeEffectsDisabled = 0x7fffffff;
       
    35 
       
    36 // --------------------------------------------------------------------------
       
    37 //
       
    38 // --------------------------------------------------------------------------
       
    39 CAknCompaSrvWsEventHandler::CAknCompaSrvWsEventHandler(RWsSession& aWsSession)
       
    40     : CActive(CActive::EPriorityStandard), iWsSession(aWsSession)
       
    41     {
       
    42     CActiveScheduler::Add(this);
       
    43     IssueRequest();
       
    44     }
       
    45 
       
    46 // --------------------------------------------------------------------------
       
    47 //
       
    48 // --------------------------------------------------------------------------
       
    49 CAknCompaSrvWsEventHandler::~CAknCompaSrvWsEventHandler()
       
    50     {
       
    51     Cancel();
       
    52     }
       
    53 
       
    54 // --------------------------------------------------------------------------
       
    55 // Issue request to read from wsrv event queue
       
    56 // --------------------------------------------------------------------------
       
    57 void CAknCompaSrvWsEventHandler::IssueRequest()
       
    58     {
       
    59     iWsSession.EventReady(&iStatus);
       
    60     SetActive();
       
    61     }
       
    62 
       
    63 // --------------------------------------------------------------------------
       
    64 // Event ready in window server event queue
       
    65 // --------------------------------------------------------------------------
       
    66 void CAknCompaSrvWsEventHandler::RunL()
       
    67     {
       
    68     // Window server event queue read to purge it in case wsrv sends
       
    69     // something. As we dont have window group created this is probably
       
    70     // unneccesary as there seem to be no events.
       
    71     TWsEvent wsEvent;
       
    72     iWsSession.GetEvent(wsEvent);
       
    73     IssueRequest();
       
    74     }
       
    75 
       
    76 // --------------------------------------------------------------------------
       
    77 //
       
    78 // --------------------------------------------------------------------------
       
    79 void CAknCompaSrvWsEventHandler::DoCancel()
       
    80     {
       
    81     iWsSession.EventReadyCancel();
       
    82     }
       
    83 
       
    84 // --------------------------------------------------------------------------
       
    85 //
       
    86 // --------------------------------------------------------------------------
       
    87 CAknCompaServer::CAknCompaServer()
       
    88     :CServer2(CActive::EPriorityStandard)
       
    89     {
       
    90     }
       
    91 
       
    92 // --------------------------------------------------------------------------
       
    93 //
       
    94 // --------------------------------------------------------------------------
       
    95 CAknCompaServer::~CAknCompaServer()
       
    96     {
       
    97     delete iThemesCenRep;
       
    98     delete iAvkonCenRep;
       
    99 
       
   100     delete iWsEventHandler;
       
   101     iWsSession.Close();
       
   102     }
       
   103 
       
   104 // --------------------------------------------------------------------------
       
   105 //
       
   106 // --------------------------------------------------------------------------
       
   107 CServer2* CAknCompaServer::NewLC()
       
   108     {
       
   109     CAknCompaServer* self = new (ELeave) CAknCompaServer;
       
   110     CleanupStack::PushL(self);
       
   111     self->ConstructL();
       
   112     return self;
       
   113     }
       
   114 
       
   115 // --------------------------------------------------------------------------
       
   116 //
       
   117 // --------------------------------------------------------------------------
       
   118 void CAknCompaServer::ConstructL()
       
   119     {
       
   120     User::LeaveIfError(iWsSession.Connect());
       
   121     iThemesCenRep = CRepository::NewL(KCRUidThemes);
       
   122     iAvkonCenRep = CRepository::NewL(KCRUidAvkon);
       
   123 
       
   124     // Check if compa-mode has disabled effects in repository
       
   125     TInt savedEffects = KAknCompaModeEffectsDisabled;
       
   126     iAvkonCenRep->Get(KAknCompaModeEffects, savedEffects);
       
   127     iEffectsDisabled = (savedEffects & KAknCompaModeEffectsSaved) != 0;
       
   128 
       
   129     iWsEventHandler = new (ELeave) CAknCompaSrvWsEventHandler(iWsSession);
       
   130     StartL(KAknCompaSrvName);
       
   131     }
       
   132 
       
   133 // --------------------------------------------------------------------------
       
   134 // New session added to server
       
   135 // --------------------------------------------------------------------------
       
   136 void CAknCompaServer::AddSession()
       
   137     {
       
   138     iSessionCount++;
       
   139     }
       
   140 
       
   141 
       
   142 // --------------------------------------------------------------------------
       
   143 // Session is closing
       
   144 // --------------------------------------------------------------------------
       
   145 void CAknCompaServer::DropSession()
       
   146     {
       
   147     if (--iSessionCount == 0)
       
   148         {
       
   149         // Stops the active scheduler. As this server runs in its 
       
   150         // own process this stop effectively kills the process
       
   151         CActiveScheduler::Stop();
       
   152         }
       
   153     }
       
   154 
       
   155 // --------------------------------------------------------------------------
       
   156 // Get window server session
       
   157 // --------------------------------------------------------------------------
       
   158 RWsSession& CAknCompaServer::WsSession()
       
   159     {
       
   160     return iWsSession;
       
   161     }
       
   162 
       
   163 // --------------------------------------------------------------------------
       
   164 // Create a new session
       
   165 // --------------------------------------------------------------------------
       
   166 CSession2* CAknCompaServer::NewSessionL(const TVersion& aVersion,
       
   167     const RMessage2& /*aMessage*/) const
       
   168     {
       
   169     // Check that the version is OK
       
   170     TVersion v(KAknCompaSrvMajorVersionNumber,
       
   171         KAknCompaSrvMinorVersionNumber, KAknCompaSrvBuildVersionNumber);
       
   172     if (!User::QueryVersionSupported(v,aVersion))
       
   173         {
       
   174         User::Leave(KErrNotSupported);          
       
   175         }
       
   176 
       
   177     return new (ELeave) CAknCompaSrvSession;
       
   178     }
       
   179 
       
   180 // --------------------------------------------------------------------------
       
   181 // Panic server
       
   182 // --------------------------------------------------------------------------
       
   183 void CAknCompaServer::PanicServer(TAknCompaServerPanic aPanic)
       
   184     {
       
   185     User::Panic(KAknCompaSrvName, aPanic);
       
   186     }
       
   187 
       
   188 // --------------------------------------------------------------------------
       
   189 // Panic client
       
   190 // --------------------------------------------------------------------------
       
   191 void CAknCompaServer::PanicClient(const RMessage2& aMessage, 
       
   192     TInt aPanic)
       
   193     {
       
   194     aMessage.Panic(KAknCompaSrvName, aPanic);
       
   195     }
       
   196 
       
   197 // --------------------------------------------------------------------------
       
   198 // Check if process is a server that displays global
       
   199 // notes/notifications (Eikon server, Avkon notify and cap servers)
       
   200 // --------------------------------------------------------------------------
       
   201 TBool CAknCompaServer::IsGlobalUiSrv(const RMessage2& aMessage)
       
   202     {
       
   203     const TUint32 KEikSrvUid = 0x10003a4a;
       
   204     return aMessage.SecureId().iId == KAknCapServerUid.iUid ||
       
   205         aMessage.SecureId().iId == KCommonNotifierAppSrvUid.iUid ||
       
   206         aMessage.SecureId().iId == KEikSrvUid;
       
   207     }
       
   208 
       
   209 // --------------------------------------------------------------------------
       
   210 // Set thread priority to normal
       
   211 // --------------------------------------------------------------------------
       
   212 void CAknCompaServer::SetThreadPriorityNormal(TAny* /*aUnused*/)
       
   213     {
       
   214     RThread thread;
       
   215     thread.SetPriority(EPriorityNormal);
       
   216     }
       
   217 
       
   218 // --------------------------------------------------------------------------
       
   219 // Set thread priority higher than any non-signed application threads
       
   220 // --------------------------------------------------------------------------
       
   221 void CAknCompaServer::SetThreadPriorityHigh()
       
   222     {
       
   223     RThread thread;
       
   224     thread.SetPriority(EPriorityAbsoluteRealTime1);
       
   225     }
       
   226 
       
   227 // --------------------------------------------------------------------------
       
   228 // Disable transition effects
       
   229 // --------------------------------------------------------------------------
       
   230 void CAknCompaServer::DisaTransEffectsL(const RMessage2& aMessage)
       
   231     {
       
   232     if (!iEffectsDisabled)
       
   233         {
       
   234         // Allow effects control only from global ui servers
       
   235         if (!IsGlobalUiSrv(aMessage))
       
   236             {
       
   237             User::Leave(KErrPermissionDenied);
       
   238             }
       
   239         iEffectsDisabled = ETrue;
       
   240         // The only way to disable transition effects is through CenRep. The
       
   241         // same variable is also controlled by "Control Panel". If the device
       
   242         // is turned off while we have disabled effects, we need to enable
       
   243         // them when device is restarted.
       
   244         TInt savedEffects = KAknCompaModeEffectsDisabled;
       
   245         iAvkonCenRep->Get(KAknCompaModeEffects, savedEffects);
       
   246 
       
   247         if ((savedEffects & KAknCompaModeEffectsSaved) == 0)
       
   248             {
       
   249             TInt effects = 0;
       
   250             iThemesCenRep->Get(KThemesTransitionEffects, effects);
       
   251             if (effects != KAknCompaModeEffectsDisabled)
       
   252                 {
       
   253                 iAvkonCenRep->Set(KAknCompaModeEffects,
       
   254                     effects | KAknCompaModeEffectsSaved);
       
   255                 iThemesCenRep->Set(KThemesTransitionEffects,
       
   256                     KAknCompaModeEffectsDisabled);
       
   257                 }
       
   258             }
       
   259         }
       
   260     }
       
   261 
       
   262 // --------------------------------------------------------------------------
       
   263 // Restore transition effects to a state before they were disabled
       
   264 // --------------------------------------------------------------------------
       
   265 void CAknCompaServer::RestoreTransEffectsL(const RMessage2& aMessage)
       
   266     {
       
   267     if (iEffectsDisabled)
       
   268         {
       
   269         // Allow effects control only from global ui servers
       
   270         if (!IsGlobalUiSrv(aMessage))
       
   271             {
       
   272             User::Leave(KErrPermissionDenied);
       
   273             }
       
   274         iEffectsDisabled = EFalse;
       
   275 
       
   276         // Read saved effects state from our CenRep
       
   277         TInt savedEffects = 0;
       
   278         iAvkonCenRep->Get(KAknCompaModeEffects, savedEffects);
       
   279 
       
   280         if (savedEffects & KAknCompaModeEffectsSaved)
       
   281             {
       
   282             savedEffects &= ~KAknCompaModeEffectsSaved;
       
   283             iThemesCenRep->Set(KThemesTransitionEffects, savedEffects);
       
   284             iAvkonCenRep->Set(KAknCompaModeEffects, savedEffects);
       
   285             }
       
   286         }
       
   287     }
       
   288 
       
   289 // --------------------------------------------------------------------------
       
   290 //
       
   291 // --------------------------------------------------------------------------
       
   292 CAknCompaServer& CAknCompaSrvSession::Server()
       
   293     {
       
   294     return *static_cast<CAknCompaServer*>
       
   295         (const_cast<CServer2*>(CSession2::Server()));
       
   296     }
       
   297 
       
   298 // --------------------------------------------------------------------------
       
   299 // Create session
       
   300 // --------------------------------------------------------------------------
       
   301 void CAknCompaSrvSession::CreateL()
       
   302     {
       
   303     // Allocate memory for keystate array to hold all possible keys.
       
   304     // This avoid possibility of memory allocation error when key is
       
   305     // added to key state array due to key press while application is
       
   306     // executing.
       
   307     iKeyState.Reserve(EKeyStateGranularity);
       
   308     
       
   309     Server().AddSession();
       
   310     }
       
   311 
       
   312 // --------------------------------------------------------------------------
       
   313 //
       
   314 // --------------------------------------------------------------------------
       
   315 CAknCompaSrvSession::CAknCompaSrvSession():
       
   316     iKeyState(EKeyStateGranularity)
       
   317     {
       
   318     // We allow only rocker keys, softkeys and numeric keypad keys to be
       
   319     // simulated.
       
   320     static const TUint8 ValidScanCodes[] =
       
   321         {
       
   322         EStdKeyDevice0, EStdKeyUpArrow, EStdKeyDevice1, EStdKeyLeftArrow,
       
   323         EStdKeyDevice3, EStdKeyRightArrow, EStdKeyRightShift,
       
   324         EStdKeyDownArrow, EStdKeyBackspace, EStdKeyNkpAsterisk, EStdKeyHash,
       
   325         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39
       
   326         };
       
   327     iValidScanCodes.Set(ValidScanCodes, sizeof(ValidScanCodes));
       
   328     }
       
   329 
       
   330 // --------------------------------------------------------------------------
       
   331 //
       
   332 // --------------------------------------------------------------------------
       
   333 CAknCompaSrvSession::~CAknCompaSrvSession()
       
   334     {
       
   335     TInt num = iKeyState.Count();
       
   336 
       
   337     // When session closes, send key up events for all keys being in down
       
   338     // state. This ensures even if application crashes that no keys are left
       
   339     // down.
       
   340     for( TInt i=0; i < num; i++)
       
   341         {
       
   342         SimulateKeyEvent(iKeyState[i], EFalse);
       
   343         }
       
   344     Server().DropSession();
       
   345     iKeyState.Close();
       
   346     }
       
   347 
       
   348 
       
   349 // --------------------------------------------------------------------------
       
   350 //
       
   351 // --------------------------------------------------------------------------
       
   352 void CAknCompaSrvSession::ServiceL(const RMessage2& aMessage)
       
   353     {
       
   354     TRAPD(err, DispatchMessageL(aMessage));
       
   355     aMessage.Complete(err);
       
   356     }
       
   357 
       
   358 // --------------------------------------------------------------------------
       
   359 //
       
   360 // --------------------------------------------------------------------------
       
   361 void CAknCompaSrvSession::DispatchMessageL(const RMessage2& aMessage)
       
   362     {
       
   363     switch(aMessage.Function())
       
   364         {
       
   365     case ECompaSrvSimulateKeyEvent:
       
   366         SimulateKeyEventServiceL(aMessage);
       
   367         break;
       
   368     case ECompaSrvDisaTransEffects:
       
   369         Server().DisaTransEffectsL(aMessage);
       
   370         break;
       
   371     case ECompaSrvRestoreTransEffects:
       
   372         Server().RestoreTransEffectsL(aMessage);
       
   373         break;
       
   374     // Requests that we don't understand at all are a different matter.
       
   375     // This is considered a client programming error, so we panic the 
       
   376     // client - this also completes the message.
       
   377     default:
       
   378         CAknCompaServer::PanicClient(aMessage, EBadRequest);
       
   379         }
       
   380     }
       
   381 
       
   382 // --------------------------------------------------------------------------
       
   383 // Simulate key event for client application
       
   384 // --------------------------------------------------------------------------
       
   385 void CAknCompaSrvSession::SimulateKeyEventServiceL(const RMessage2& aMessage)
       
   386     {
       
   387     TInt scancode = aMessage.Int0();
       
   388     TBool keyDown = aMessage.Int1();
       
   389 
       
   390     // Check that scan code is valid. Client request will fail with error
       
   391     // code KErrNotFound if the check fails.
       
   392     TChar ch(scancode);
       
   393     User::LeaveIfError(iValidScanCodes.Locate(ch));
       
   394 
       
   395     if (keyDown)
       
   396         {
       
   397         // Set thread priority to very high. The purpose is to prevent
       
   398         // other threads to change foreground application in between
       
   399         // client foreground status check and SimulateRawEvent().
       
   400         CAknCompaServer::SetThreadPriorityHigh();
       
   401         CleanupStack::PushL(
       
   402             TCleanupItem(CAknCompaServer::SetThreadPriorityNormal, NULL));
       
   403         // Check that client task is foreground
       
   404         CheckKeyDownPermissionL(aMessage);
       
   405         }
       
   406 
       
   407     // Keeps tracks which scancodes are in down state
       
   408     if (keyDown)
       
   409         {
       
   410         // There can be only one of each scancode in the list
       
   411         if (iKeyState.Find(scancode) == KErrNotFound)
       
   412             {
       
   413             iKeyState.AppendL(scancode);
       
   414             SimulateKeyEvent(scancode, keyDown);
       
   415             }
       
   416         CleanupStack::PopAndDestroy();
       
   417         }
       
   418     else
       
   419         {
       
   420         TInt pos = iKeyState.Find(scancode);
       
   421         if (pos != KErrNotFound)
       
   422             {
       
   423             iKeyState.Remove(pos);
       
   424             iKeyState.GranularCompress();
       
   425             SimulateKeyEvent(scancode, keyDown);
       
   426             }
       
   427         }
       
   428     }
       
   429 
       
   430 // --------------------------------------------------------------------------
       
   431 // Simulate key event to window server
       
   432 // --------------------------------------------------------------------------
       
   433 void CAknCompaSrvSession::SimulateKeyEvent(TInt aScancode, TBool aKeyDown)
       
   434     {
       
   435     TRawEvent event;
       
   436     event.Set(
       
   437         aKeyDown ? TRawEvent::EKeyDown : TRawEvent::EKeyUp,
       
   438         aScancode);
       
   439 
       
   440     RWsSession& wsSession = Server().WsSession();
       
   441     // Simulate key event as it came from a keypad
       
   442     wsSession.SimulateRawEvent(event);
       
   443     wsSession.Flush();
       
   444     }
       
   445 
       
   446 // --------------------------------------------------------------------------
       
   447 // Check whether client key event request can be executed
       
   448 // --------------------------------------------------------------------------
       
   449 void CAknCompaSrvSession::CheckKeyDownPermissionL(const RMessage2& aMessage)
       
   450     {
       
   451     // We try to increase security by allowing only foreground application
       
   452     // to set key down. As the simulated key events are sent to the
       
   453     // foreground application by window server, the application is
       
   454     // sending a key event to itself.
       
   455 
       
   456     // Granted if client has ECapabilitySwEvent or request is coming from
       
   457     // EikSrv. TApaTaskList won't report EikSrv in foreground though
       
   458     // it's displaying a note.
       
   459     if (!aMessage.HasCapability(ECapabilitySwEvent) &&
       
   460         !CAknCompaServer::IsGlobalUiSrv(aMessage))
       
   461         {
       
   462         // Allow key down only from a foreground task
       
   463         TApaTaskList tasklist(Server().WsSession());
       
   464         TApaTask foregroundTask = tasklist.FindByPos(0);
       
   465 
       
   466         RThread thread;
       
   467         User::LeaveIfError(thread.Open(foregroundTask.ThreadId()));
       
   468         TSecurityPolicy securityPolicy(thread.SecureId());
       
   469         thread.Close();
       
   470 
       
   471         if (!securityPolicy.CheckPolicy(aMessage))
       
   472             {
       
   473             User::Leave(KErrPermissionDenied);
       
   474             }
       
   475         }
       
   476     }