diff -r 000000000000 -r 2f259fa3e83a uifw/EikStd/srvuisrc/EIKSRVUI.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/EikStd/srvuisrc/EIKSRVUI.CPP Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,1971 @@ +/* +* Copyright (c) 2002-2007 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: +* +*/ + +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include "eikkwin.h" +#include +#include + +#include +#include +#include + +#define __ASSHDBITFLAGS_H__ + +#include +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#endif +#include +#include +#include +#include "EIKNFYUI.H" +#include +#include + +/* +* Following resources used from Symbian's eikpriv.rss file: +* +* r_eik_system_default_view_id +* r_eik_system_view_server_event_time_out +* r_eik_system_view_server_client_request_time_out +*/ +#include +#include "EIKSRV.HRH" + +#include +#include +#include +#include +#include "eikkeysoundserver.h" +#include +#include +#include + +#include +#include +#include +#include + +#include +#include // KUikLayoutState + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "e32uid.h" + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "EikLafShutStarter.h" +#include "EikLafShutScheduler.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "AknNotifierControllerPlugin.h" +#include +#include "AknEikSrv.pan" + +#if defined(__WINS__) +const TInt KEikServSideBarWidth = 35; +const TInt KEikServAppbarHeight = 50; +#endif + +#if defined (__WINS__) +_LIT(COMMS_PDD_NAME, "ECDRV"); +_LIT(COMMS_LDD_NAME, "ECOMM"); +#else +_LIT(COMMS_PDD_NAME, "EUART1"); +_LIT(COMMS_LDD_NAME, "ECOMM"); +#endif + +const TInt KEikServServerRestartDelay = 500000; // .5 sec +const TInt KEikServServerRestartInterval = 3000000; // 3 sec + +_LIT(KResFileName, "z:\\resource\\eiksrvui.rsc"); +_LIT(KAnimDllFileName, "AknAnimDll.Dll"); +_LIT(KWatcherThreadName, "UikonWatchers"); + +const TInt KEikServPanicTextBufferSize = 512; + +GLDEF_C void Panic(TEikServPanic aPanic) + { + _LIT(KPanicCat,"EIKON-SERVER"); + User::Panic(KPanicCat,aPanic); + } + +#define iAknCapServerClient (*(CAknSgcClient::AknSrv())) + +class CFbsBitmap; + +// ===================== +// RKeySoundServerCloser +// ===================== + +class RKeySoundServerCloser : public RSessionBase + { +public: + void CloseServer(); + }; + +void RKeySoundServerCloser::CloseServer() + { + if (CreateSession(__KEYSOUND_SERVER_NAME, TVersion(KKeySoundServMajorVN, KKeySoundServMinorVN, + KKeySoundServBuildVN), 0) == KErrNone) + { + SendReceive(EKeySoundServerCloseServer, TIpcArgs()); + Close(); + } + } + +// ================== +// CEikServAppStarter +// ================== + +class CEikServAppStarter : public CBase, public MVwsAppStarter + { +public: + static CEikServAppStarter* NewL(); + ~CEikServAppStarter(); +public: // From MVwsAppStarter. + void StartAppL(TUid aAppUid, TThreadId& aThreadId); +private: + CEikServAppStarter(); + void ConstructL(); +private: + }; + +CEikServAppStarter* CEikServAppStarter::NewL() + { + CEikServAppStarter* self=new(ELeave) CEikServAppStarter; + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +CEikServAppStarter::~CEikServAppStarter() + { + } + +CEikServAppStarter::CEikServAppStarter() + { + } + +void CEikServAppStarter::ConstructL() + { + } + +void CEikServAppStarter::StartAppL(TUid aAppUid, TThreadId& aThreadId) + { + RApaLsSession ls; + CleanupClosePushL(ls); + User::LeaveIfError(ls.Connect()); + TApaAppInfo info; + TInt err = ls.GetAppInfo(info,aAppUid); + + User::LeaveIfError(err); + + // LeaveIfError does not trigger to positive values, but GetAppInfo does not return valid + // data unless server returns KErrNone. + if ( err > 0 ) + { + User::Leave(KErrNotReady); + } + + CApaCommandLine* cmdLine = CApaCommandLine::NewLC(); + cmdLine->SetExecutableNameL(info.iFullName); + cmdLine->SetCommandL(EApaCommandViewActivate); + + // Using apparc client-server to do this "internal" launch. + ls.StartApp(*cmdLine, aThreadId); + CleanupStack::PopAndDestroy(); // cmdLine + CleanupStack::PopAndDestroy(); // ls + } + +// Thread function for OOD watcher. +GLDEF_C TInt WatcherThreadFunction(TAny* /*aParameters*/) + { + TInt err(KErrNone); + + CTrapCleanup* cleanup = CTrapCleanup::New(); + CActiveScheduler* scheduler = new CEikLafShutScheduler(); + CEikLafShutStarter* lafShut = NULL; + + if (!cleanup || !scheduler) + { + err = KErrNoMemory; + } + + else + { + CActiveScheduler::Install(scheduler); + TRAP(err, + { + RThread me; + me.SetPriority(EPriorityLess); + lafShut = CEikLafShutStarter::NewL(); + }) + + if (err == KErrNone) + { + // start the watchers + CActiveScheduler::Start(); + } + } + + delete cleanup; + delete scheduler; + delete lafShut; + + return err; + } + +// Creates thread for OOM & OOD watchers. +GLDEF_C void CreateWatcherThreadL() + { + RThread thread; + + TInt ret = thread.Create( + KWatcherThreadName, + WatcherThreadFunction, + 0x2000, // stack size + NULL, // uses caller thread's heap + (TAny*)NULL ); + + if (ret == KErrNone) + { + thread.Resume(); + thread.Close(); + } + + User::LeaveIfError(ret); + } + +// ================== +// CEikSrvAppShutdown +// ================== + +NONSHARABLE_CLASS(CEikSrvAppShutdown) : public CActive + { +public: + static void StartL( + const TUid aRequesterUID, + const RMessage2& aShutdownMessage, + const TInt aTimeoutInMicroseconds); +private: + CEikSrvAppShutdown(const RMessage2& aShutdownMessage); + ~CEikSrvAppShutdown(); + void DoCancel(); + void RunL(); +private: + RMessagePtr2 iMessage; + }; + +void CEikSrvAppShutdown::StartL(const TUid aRequesterUID, const RMessage2& aShutdownMessage, + const TInt aTimeoutInMicroseconds) + { + if (iAknCapServerClient.Handle()) + { + CEikSrvAppShutdown* self = new(ELeave) CEikSrvAppShutdown(aShutdownMessage); + iAknCapServerClient.ShutdownApps(aRequesterUID, aTimeoutInMicroseconds, self->iStatus); + self->SetActive(); + } + else + aShutdownMessage.Complete(KErrNone); + } + +CEikSrvAppShutdown::CEikSrvAppShutdown(const RMessage2& aShutdownMessage) +: CActive(CActive::EPriorityStandard), iMessage(aShutdownMessage) + { + CActiveScheduler::Add(this); + } + +CEikSrvAppShutdown::~CEikSrvAppShutdown() + { + Cancel(); + } + +void CEikSrvAppShutdown::DoCancel() + { + } + +void CEikSrvAppShutdown::RunL() + { + iMessage.Complete(KErrNone); + delete this; + } + +// ============= +// CEikServExtra +// ============= + +class CEikServExtra : public CBase + { +public: + CPeriodic* iServerRestarter; + CArrayPtr* iPointerCursors; + CIdle* iNotifierServerStarter; + }; + +const TInt KEiksrvUiDllValue = 0x100053D0; + + +EXPORT_C CEikServAppUiBase* CEikServAppUiBase::NewLC() + { + if (CEikonEnv::Static()->WsSession().FindWindowGroupIdentifier( + 0, __EIKON_SERVER_NAME, 0) > KErrNotFound) + { + return NULL; // Already an Eikon server running. + } + + // This code duplicates what is in EikSrv.cpp in CEikServAppUiServer::CreateAppUiL(). + _LIT(KRomPath, "\\System\\Libs\\"); + _LIT(KEiksrvUiDllName, "EiksrvUi.dll"); + TFileName path; + Dll::FileName(path); + const TUint16& drv = path[0]; + if (drv == 'z' || drv == 'Z') + { + path.Append(KRomPath); + } + else + { + TParse parse; + User::LeaveIfError(parse.Set(path, NULL, NULL)); + path = parse.DriveAndPath(); + } + TUidType uidType(KDynamicLibraryUid, KSharedLibraryUid, TUid::Uid(KEiksrvUiDllValue)); + RLibrary lib; + User::LeaveIfError(lib.Load(KEiksrvUiDllName, path, uidType)); + CleanupClosePushL(lib); + TLibraryFunction appui = lib.Lookup(1); + CEikServAppUiBase* self = REINTERPRET_CAST(CEikServAppUiBase*, (*appui)()); + User::LeaveIfNull(self); + STATIC_CAST(CEikServEnv*, CEikonEnv::Static())->SetUiDll(lib); + CleanupStack::Pop(); // lib + CleanupStack::PushL(self); + STATIC_CAST(CEikAppUi*, self)->ConstructL(); + + return self; + } + +EXPORT_C void CEikServAppUiBase::NotifyAlarmServerOfTaskChangeL() + { + if (iAlarmAlertServer) + { + iAlarmAlertServer->TaskKeyPressedL(); + } + } + +EXPORT_C void CEikServAppUiBase::EnableTaskListL() + { + User::Leave(KErrNotSupported); + } + +EXPORT_C void CEikServAppUiBase::LaunchTaskListL() + { + User::Leave(KErrNotSupported); + } + +EXPORT_C void CEikServAppUiBase::CycleTasksL(enum TTaskCycleDirection aDirection) + { + TApaTaskList taskList(iCoeEnv->WsSession()); + if (aDirection == EBackwards) + { + TApaTask task = taskList.FindByPos(-1); + task.BringToForeground(); + } + else + { + TApaTask task = taskList.FindByPos(0); + task.SendToBackground(); + } + + // Will also task away from alarm when only 1 task!! Correct? + NotifyAlarmServerOfTaskChangeL(); + } + +EXPORT_C CEikServAppUiBase::CEikServAppUiBase() + { + SetFullScreenApp(EFalse); + } + +LOCAL_C void ReleaseFactories(TAny* aPtr) + { + TEikServCtrlFactories& factory = *(TEikServCtrlFactories*)aPtr; + if (factory.iAlert) + { + factory.iAlert->Release(); + } + } + +LOCAL_C void PointerCleanup(TAny* aPtr) + { + RWsPointerCursor* ptr = REINTERPRET_CAST(RWsPointerCursor*, aPtr); + ptr->Close(); + delete ptr; + } + +EXPORT_C void CEikServAppUiBase::ConstructL() + { + RWindowGroup& groupWin = iCoeEnv->RootWin(); + RWsSession& wsSession = iCoeEnv->WsSession(); + iEikonEnv->SetAutoForwarding(ETrue); + iEikonEnv->SetSystem(ETrue); + iEikonEnv->FsSession().SetNotifyUser(EFalse); + + // Must call BaseConstructL to get Avkon classes called. +#ifdef _DEBUG + RDebug::Print(_L("CAknAppUiBase::BaseConstructL() in ")); +#endif + CAknAppUiBase::BaseConstructL(ENonStandardResourceFile|ENoScreenFurniture| + EAknEnableMSK|EAknSingleClickCompatible); +#ifdef _DEBUG + RDebug::Print(_L("CAknAppUiBase::BaseConstructL() out")); +#endif + + groupWin.SetName(__EIKON_SERVER_NAME); + groupWin.EnableErrorMessages(EEventControlAlways); + groupWin.EnableOnEvents(EEventControlAlways); + wsSession.ComputeMode(RWsSession::EPriorityControlDisabled); + iCoeEnv->RootWin().EnableScreenChangeEvents(); + RThread thread; + +#if defined(__EPOC32__) + thread.SetProcessPriority(EPriorityHigh); +#else + thread.SetPriority(EPriorityAbsoluteForeground); +#endif + + // Create a window group for the password and alarm screens. + iAlertGroupWin = RWindowGroup(wsSession); + + // EFalse disables key events - they will be enabled again as soon as the ordinal position is + // set such that iAlertGroupWin is not the foreground window-group. + User::LeaveIfError(iAlertGroupWin.Construct((TUint32)this, EFalse)); + + iAlertGroupWin.SetOrdinalPosition(0, ECoeWinPriorityNeverAtFront); + + // Enable key events, now that iAlertGroupWin is not in the foreground. + iAlertGroupWin.EnableReceiptOfFocus(ETrue); + + iEikServExtra = new(ELeave) CEikServExtra(); + + TInt numCursors = LafServAppUiBase::NumberOfCursorsInSystemCursorList(); + if(numCursors != 0 && LafServAppUiBase::ClaimPointerCursorListIfNeeded(*iEikonEnv) == KErrNone) + { + iEikServExtra->iPointerCursors = new(ELeave) CArrayPtrFlat(4); + TSpriteMember member; + for(TInt ii = 0; ii < numCursors; ii++) + { + RWsPointerCursor* cursor = LafServAppUiBase::ConstructPointerCursorL(ii, member, + *iEikonEnv); + + CleanupStack::PushL(TCleanupItem(PointerCleanup, cursor)); + iEikServExtra->iPointerCursors->AppendL(cursor); + CleanupStack::Pop(); // cursor - handle & ptr + } + } + } + +EXPORT_C void CEikServAppUiBase::InitializeL(TEikServCtrlFactories& aCtrlFactories) + { + RWindowGroup& rootWin = iCoeEnv->RootWin(); + + CleanupStack::PushL(TCleanupItem(&ReleaseFactories,&aCtrlFactories)); + RFs& fsSession = iCoeEnv->FsSession(); + _LIT(KAppDirName, "C:\\System\\Apps\\"); + fsSession.MkDirAll(KAppDirName); // !! prevent app arch crash + + // Initialize some system settings. + SetSystemTime(); + rootWin.EnableOnEvents(EEventControlAlways); + + TPasswordMode mode = EPasswordNone; + + TRAP_IGNORE( + CEikPasswordModeCategory* pcategory = CEikPasswordModeCategory::NewLC(fsSession); + if( pcategory ) + { + pcategory->GetPasswordModeL(mode); + if (mode == EPasswordNone) // prevent overwriting once per day + { + mode = EPasswordAlways; + } + // Initialise (write to system.ini) here so that it won't fail in the future due to OOM. + pcategory->SetPasswordModeL(mode); + CleanupStack::PopAndDestroy(); // pcategory + } + ); + + // Create separate thread for OOD watchers. + CreateWatcherThreadL(); + + // Start View Server. + iAppStarter = CEikServAppStarter::NewL(); + User::LeaveIfError(CVwsSessionWrapper::StartViewServer(*iAppStarter)); + iVwsSession = CVwsSessionWrapper::NewL(); + + TResourceReader reader; + iEikonEnv->CreateResourceReaderLC(reader, R_EIK_SYSTEM_DEFAULT_VIEW_ID); + TVwsViewId viewId; + viewId.iAppUid.iUid = reader.ReadInt32(); + viewId.iViewUid.iUid = reader.ReadInt32(); + CleanupStack::PopAndDestroy(); // reader + iVwsSession->SetSystemDefaultView(viewId); + + TInt serverEventTimeOutDuration = EikResourceUtils::ReadTInt32L( + R_EIK_SYSTEM_VIEW_SERVER_EVENT_TIME_OUT, iEikonEnv); + + iVwsSession->SetServerEventTimeOut( TTimeIntervalMicroSeconds32(serverEventTimeOutDuration) ); + + TInt clientRequestTimeOutDuration = EikResourceUtils::ReadTInt32L( + R_EIK_SYSTEM_VIEW_SERVER_CLIENT_REQUEST_TIME_OUT, iEikonEnv); + + iVwsSession->SetClientRequestTimeOut( TTimeIntervalMicroSeconds32(clientRequestTimeOutDuration) ); + + iVwsSession->EnableServerBlankScreen(EFalse); + + // Start Comms + TInt err = StartC32(); + if (err != KErrNone && err != KErrAlreadyExists) + { + User::Leave(err); + } + + err = User::LoadPhysicalDevice(COMMS_PDD_NAME); + if (err != KErrNone && err != KErrAlreadyExists && err != KErrNotFound) + { + User::Leave(err); + } + + err = User::LoadLogicalDevice(COMMS_LDD_NAME); + if (err != KErrNone && err != KErrAlreadyExists && err != KErrNotFound) + { + User::Leave(err); + } + + // Start notifier server last as these may have plug-ins that rely on the other servers + // started here being up and running. + iNotifyServer = CEikServNotifyServer::NewL(aCtrlFactories.iAlert); + + CleanupStack::Pop(); // aCtrlFactories + + iEikServExtra->iNotifierServerStarter = CIdle::NewL(CActive::EPriorityLow); + iEikServExtra->iNotifierServerStarter->Start(TCallBack(StartNotifierServerCallBackL, this)); + + rootWin.EnableGroupListChangeEvents(); + + // Create undertaker active object. + iUndertaker = CEikUndertaker::NewL(*this); + + // Create an active object to restart servers. + iEikServExtra->iServerRestarter = CPeriodic::NewL(CActive::EPriorityStandard); + } + +EXPORT_C void CEikServAppUiBase::HandleThreadExitL(RThread& aThread) + { + if (aThread.Name() == ASCliDefinitions::ServerAndThreadName()) // alarm server died + { + aThread.Close(); // need to Close() before restarting with same name + iServerToRestart |= EAlwlSvr; // restarted under active object + } + else if (aThread.Name()==NameApaServServerThread()) // AppArc server died + { + aThread.Close(); + iServerToRestart|=EApaSvr; + } + + if (iServerToRestart && !iEikServExtra->iServerRestarter->IsActive()) + { + iEikServExtra->iServerRestarter->Start( + KEikServServerRestartDelay, + KEikServServerRestartInterval, + TCallBack(RestartServerCallback, this)); + } + } + +EXPORT_C void CEikServAppUiBase::HandleForegroundEventL(TBool aForeground) + { + CAknAppUiBase::HandleForegroundEventL(aForeground); + } + +TInt CEikServAppUiBase::RestartServerCallback(TAny* aObj) + { + STATIC_CAST(CEikServAppUiBase*, aObj)->RestartServer(); + return KErrNone; + } + +TInt CEikServAppUiBase::StartNotifierServerCallBackL(TAny* aPtr) + { // static + CEikServAppUiBase* self = static_cast(aPtr); + self->iNotifyServer->StartL(); + delete self->iEikServExtra->iNotifierServerStarter; + self->iEikServExtra->iNotifierServerStarter=NULL; + return KErrNone; + } + +// Kick dead servers back to life, if we can connect then stop kicking. +void CEikServAppUiBase::RestartServer() + { + if (iServerToRestart & EAlwlSvr) + { + // Start AlarmServer + TInt err = AlarmClientUtils::StartAlarmServer(); + if (err == KErrNone) + { + iServerToRestart&=(~EAlwlSvr); + } + } + + if (iServerToRestart&EApaSvr) + { + AknStartupApaServerProcess(); + + // try to connect to the server + RApaLsSession ls; + TInt err = ls.Connect(); + if (err == KErrNone) + { + ls.Close(); + iServerToRestart&=(~EApaSvr); + } + } + + if (!iServerToRestart) + { + iEikServExtra->iServerRestarter->Cancel(); + } + } + +EXPORT_C TKeyResponse CEikServAppUiBase::HandleKeyEventL(const TKeyEvent& aKeyEvent, + TEventCode /*aType*/) + { + if (aKeyEvent.iCode == CTRL('e')) + { + CBaActiveScheduler::Exit(); + } + return EKeyWasConsumed; + } + +// Check the battery states and update any alarm snooze time. +EXPORT_C void CEikServAppUiBase::HandleSwitchOnEventL(CCoeControl* /*aDestination*/) + { + // Could just expose alarm alert server to UI dll!! + if (iAlarmAlertServer) + { + iAlarmAlertServer->HandleSwitchOnEvent(); + } + } + +EXPORT_C void CEikServAppUiBase::HandleSystemEventL(const TWsEvent& aEvent) + { + TInt event = *((TInt*)aEvent.EventData()); + switch (event) + { +#ifdef _DEBUG + case EEikServExit: + CBaActiveScheduler::Exit(); + break; +#endif + default: + break; + } + } + +EXPORT_C void CEikServAppUiBase::HandleApplicationSpecificEventL(TInt aType, const TWsEvent& aEvent) + { + // Check command/number or whatever first!! + CAknAppUiBase::HandleApplicationSpecificEventL(aType, aEvent); + } + + +EXPORT_C CEikServAppUiBase::~CEikServAppUiBase() + { + delete iUndertaker; + + if (iEikServExtra) + { + delete iEikServExtra->iServerRestarter; + + if (iEikServExtra->iPointerCursors) + { + const TInt count = iEikServExtra->iPointerCursors->Count(); + + for (TInt ii = 0; ii < count; ii++) + { + (*(iEikServExtra->iPointerCursors))[ii]->Close(); + } + + iEikServExtra->iPointerCursors->ResetAndDestroy(); + delete iEikServExtra->iPointerCursors; + } + + delete iEikServExtra->iNotifierServerStarter; + delete iEikServExtra; + } + + LafServAppUiBase::FreePointerCursorListIfNeeded(*iEikonEnv); + RWindowGroup& groupWin = iEikonEnv->RootWin(); + groupWin.DisableErrorMessages(); + groupWin.DisableOnEvents(); + iAlertGroupWin.Close(); + delete iNotifyServer; + delete iAlarmAlertServer; + delete iAppStarter; + + if (iVwsSession) + { + iVwsSession->ShutdownViewServer(); + delete iVwsSession; + } + } + +void CEikServAppUiBase::SetSystemTime() const + { + // Deprecated, we don't have capability to set system time. + } + +// Bring to foreground or send to background appropriately. +EXPORT_C void CEikServAppUiBase::BringAlertGroupWinForwards(TBool aForwards) + { + if (aForwards) + { + if (!iAlertGroupForwardsCount++) + { + iAlertGroupWin.SetOrdinalPosition(0, KMaxTInt); + } + } + else if (--iAlertGroupForwardsCount == 0) + { + iAlertGroupWin.SetOrdinalPosition(0, ECoeWinPriorityNeverAtFront); + } + } + +EXPORT_C void CEikServAppUiBase::SetStatusPaneFlags(TInt /*aFlags*/) + { + User::Leave(KErrNotSupported); + } + +EXPORT_C void CEikServAppUiBase::SetStatusPaneLayoutL(TInt /*aLayoutResId*/) + { + User::Leave(KErrNotSupported); + } + +EXPORT_C void CEikServAppUiBase::BlankScreenL() + { + User::Leave(KErrNotSupported); + } + +EXPORT_C void CEikServAppUiBase::UnblankScreen() + { + User::Leave(KErrNotSupported); + } + +EXPORT_C void CEikServAppUiBase::ShutdownAppsL(const TUid aRequesterUID, + const RMessage2& aShutdownMessage, const TInt aTimeoutInMicroseconds) + { + CEikSrvAppShutdown::StartL(aRequesterUID, aShutdownMessage, aTimeoutInMicroseconds); + } + +EXPORT_C void CEikServAppUiBase::HandleResourceChangeL(TInt aType) + { + CAknAppUiBase::HandleResourceChangeL(aType); + } + +void CEikServAppUiBase::Extension(TUid /*aExtensionUid*/, const TDesC8& /*aBuffer*/, + RMessagePtr2 /*aMessage*/) + { + // Not implemented + } + +EXPORT_C void CEikServAppUiBase::HandleWsEventL(const TWsEvent& aEvent,CCoeControl* aDestination) + { + CAknAppUiBase::HandleWsEventL(aEvent, aDestination); + } + +void CEikServAppUiBase::SetSgcParamsL(TInt /*aWgId*/, TBitFlags /*aAppFlags*/, TInt /*aSpLayout*/, + TInt /*aSpFlags*/) + { + } + +void CEikServAppUiBase::PrepareForAppExitL(TInt /*aWgId*/) + { + } + + +// ============= +// CEikServAppUi +// ============= + +void CEikServAppUi::SetStatusPaneFlags(TInt aFlags) + { + if (iAknCapServerClient.Handle()) + { + iAknCapServerClient.SetStatusPaneFlags(aFlags); + } + } + +void CEikServAppUi::SetStatusPaneLayoutL(TInt aLayoutResId) + { + if (iAknCapServerClient.Handle()) + { + iAknCapServerClient.SetStatusPaneLayout(aLayoutResId); + } + } + +void CEikServAppUi::BlankScreenL() + { + if (iAknCapServerClient.Handle()) + { + iAknCapServerClient.BlankScreen(); + } + } + +void CEikServAppUi::UnblankScreen() + { + if (iAknCapServerClient.Handle()) + { + iAknCapServerClient.UnblankScreen(); + } + } + +void CEikServAppUi::EnableTaskListL() + { + User::LeaveIfError(iAknCapServerClient.EnableTaskList(ETrue)); + } + +void CEikServAppUi::LaunchTaskListL() //const + { + User::LeaveIfError(iAknCapServerClient.MakeTaskListVisible(ETrue)); + } + +void CEikServAppUi::CloseTaskList() //const + { + // Ignore possible error. + iAknCapServerClient.MakeTaskListVisible(EFalse); + } + +CEikServAppUi::CEikServAppUi() + { + } + +void CEikServAppUi::ConstructL() + { + // Create stub to allow device boot up with old notifier controller dependencies. + iNotifierDialogController = CNotifierDialogController::NewL(0); + +#ifdef _DEBUG + RDebug::Print(_L("CEikServAppUi::ConstructL() in")); +#endif + + AknsUtils::InitSkinSupportL(); +#ifdef _DEBUG + RDebug::Print(_L("CEikServAppUi::ConstructL() init skins ok")); +#endif + + CEikServAppUiBase::ConstructL(); +#ifdef _DEBUG + RDebug::Print(_L("CEikServAppUi::ConstructL() CEikServAppUiBase constructed")); +#endif + + AknsUtils::SetAvkonSkinEnabledL( ETrue ); +#ifdef _DEBUG + RDebug::Print(_L("CEikServAppUi::ConstructL(), CEikServAppUiBase::ConstructL() succeed")); +#endif + + AknsUtils::SetAvkonSkinEnabledL( ETrue ); +#ifdef _DEBUG + RDebug::Print(_L("CEikServAppUiBase::ConstructL(), Skins enabled")); +#endif + + TFileName fileName(KResFileName); + BaflUtils::NearestLanguageFile(iEikonEnv->FsSession(), fileName); + iResourceFileOffset = iCoeEnv->AddResourceFileL(fileName); + + // Create notifier controller before Notfier server is started. + iNotifierController = CAknNotifierController::NewL(); + +#ifdef _DEBUG + RDebug::Print(_L("CEikServAppUi::ConstructL(), initializing Alert")); +#endif + + CEikServNotifyAlert* alert=new(ELeave) CEikServNotifyAlert; + CleanupStack::PushL(alert); + alert->ConstructL(); + TEikServCtrlFactories fctry; + fctry.iAlert = alert; + fctry.iAlarmAlert = this; + CleanupStack::Pop(); + +#ifdef _DEBUG + RDebug::Print(_L("CEikServAppUi::ConstructL(), Alert created")); +#endif + + CEikServAppUiBase::InitializeL(fctry); + +#ifdef _DEBUG + RDebug::Print(_L("CEikServAppUiBase::InitializeL(fctry) succeed")); +#endif + + RWsSession& wsSession = iCoeEnv->WsSession(); + + // Initialize some system settings. + TRAP_IGNORE(EnsureExternalKeyHandlerAppStreamExistsL()); + +#ifdef _DEBUG + RDebug::Print(_L("CEikServAppUi::ConstructL(), Creating WG for status pane")); +#endif + + // Create high priority windows for app bar and side bar. + iOffScreenGroupWin = RWindowGroup(wsSession); + User::LeaveIfError(iOffScreenGroupWin.Construct((TUint32)&iOffScreenGroupWin, + EFalse)); // EFalse disables key events + iOffScreenGroupWin.SetOrdinalPosition(0,ECoeWinPriorityHigh); + +#ifdef _DEBUG + RDebug::Print(_L("CEikServAppUi::ConstructL(), Starting sound server")); +#endif + + // Launch the Avkon KeySound Server + User::LeaveIfError(CEikKeySoundServer::LaunchServer(iKeySoundThreadId)); + + // Start the Avkon Anim Dll - required for keysounds + iAknAnimDll = new(ELeave)RAnimDll(wsSession); + iAknAnimDll->Load(KAnimDllFileName); + iAknAnimKeySound = new(ELeave)RAknAnimKeySound(*iAknAnimDll); + iAknAnimKeySound->ConstructL(&iOffScreenGroupWin); + +#ifdef _DEBUG + RDebug::Print(_L("CEikServAppUi::ConstructL(), Keysounds and plugin initialized")); +#endif + + // Create default keysounds - pass in UID. + ReplaceKeySoundsL(0x100053D0); + +#ifdef _DEBUG + RDebug::Print(_L("CEikServAppUi::ConstructL(), Default client and context for keysound created ")); +#endif + + // Window server buffer size. + RWsSession &ws = iEikonEnv->WsSession(); + TInt bufSize = 6400; + ws.SetMaxBufferSizeL(bufSize); + + // Load bitmap cursors. + LoadBitmapCursorsL(); + + STATIC_CAST(CEikServEnv*,CEikonEnv::Static())->SetEikServAppUiSessionFactory( this ); + +#ifdef _DEBUG + RDebug::Print(_L("CEikServAppUi::ConstructL(), over and out")); +#endif + } + + +void CEikServAppUi::RestartKeySoundThreadL() + { + // Restart keysound server. + TInt err = CEikKeySoundServer::LaunchServer(iKeySoundThreadId); + if (err != KErrNone) + { + // Server cannot be restarted, so leave existing animation dll. + // No sounds will be played, but machine will still operate. + return; + } + + // Restart the animation dll + if (iAknAnimKeySound) + { + iAknAnimKeySound->Close(); + delete iAknAnimKeySound; + iAknAnimKeySound = NULL; + } + + if (iAknAnimDll) + { + iAknAnimDll->Close(); + delete iAknAnimDll; + iAknAnimDll = NULL; + } + + // Restart the animation dll. + iAknAnimDll = new(ELeave)RAnimDll(iCoeEnv->WsSession()); + iAknAnimDll->Load(KAnimDllFileName); + iAknAnimKeySound = new(ELeave)RAknAnimKeySound(*iAknAnimDll); + iAknAnimKeySound->ConstructL(&iOffScreenGroupWin); + + // Invented new API. + ReplaceKeySoundsL(0x100053D0); + KeySounds()->BringToForeground(); + } + + +void CEikServAppUi::HandleThreadExitL(RThread& aThread) + { + if(aThread.Name().CompareF(_L("aknnfysrv")) == 0) + { + StartNewServerApplicationL(KCommonNotifierAppSrvUid); + return; + } + + TThreadId id = aThread.Id(); + TExitType exitType = aThread.ExitType(); + if (id == iExternalKeyHandlerThreadId) + { + iExternalKeyHandlerRunning = EFalse; + } + else if (id == iHelpAppThreadId) + { + iHelpAppRunning = EFalse; + } + else if (id == iKeySoundThreadId) + { + RestartKeySoundThreadL(); + // Don't tell the user about it. + return; + } + + TBool rdSupport = BaflUtils::FileExists( iEikonEnv->FsSession(), KRDSupport ); + + // Show panic notes only if that feature is enabled. + if ( exitType == EExitPanic && ( rdSupport || FeatureManager::FeatureSupported( + KFeatureIdShowPanics )) ) + { + // Construct text for a panic note. + HBufC* panicText = ConstructPanicTextLC( aThread, rdSupport ); + + iAknCapServerClient.ShowGlobalNoteL(panicText->Des(), EAknGlobalErrorNote); + CleanupStack::PopAndDestroy(); // panicText + } + + CEikServAppUiBase::HandleThreadExitL(aThread); + } + +void CEikServAppUi::UpdateTaskListL() + { + iAknCapServerClient.UpdateTaskList(); + } + +TKeyResponse CEikServAppUi::HandleKeyEventL(const TKeyEvent& aKeyEvent, TEventCode /*aType*/) + { + if (aKeyEvent.iCode == CTRL('e')) // Exit + { + CBaActiveScheduler::Exit(); + } + return EKeyWasConsumed; + } + +void CEikServAppUi::HandleWsEventL(const TWsEvent& aEvent, CCoeControl* aDestination) + { + switch (aEvent.Type()) + { + case EEventPassword: + { + // No action in Avkon. + break; + } + case EEventErrorMessage: + HandleErrorMessageEvent(*(aEvent.ErrorMessage())); + break; + case KUidValueAknsSkinChangeEvent: + { + HandleResourceChangeL(KAknsMessageSkinChange); + HandleStackedControlsResourceChange(KAknsMessageSkinChange); + break; + } + default: + CEikServAppUiBase::HandleWsEventL(aEvent, aDestination); + break; + } + } + +// Handle an error message from the window server. +void CEikServAppUi::HandleErrorMessageEvent(const TWsErrorMessage& aErrorMessage) + { + TUint err = aErrorMessage.iError; + + switch (aErrorMessage.iErrorCategory) + { + case TWsErrorMessage::EDrawingRegion: + HandleOomEvent(); + break; + case TWsErrorMessage::EBackLight: + HandleBacklightError(err); + break; + case TWsErrorMessage::ELogging: + HandleWservLoggingError(err); + break; + default: + break; // intentionally ignored + } + } + +void CEikServAppUi::HandleResourceChangeL(TInt aType) + { + CEikServAppUiBase::HandleResourceChangeL(aType); + if ( aType == KEikDynamicLayoutVariantSwitch ) + { + UpdateCursorsL(); + } + } + +// Check the battery states and update any alarm snooze time. +void CEikServAppUi::HandleSwitchOnEventL(CCoeControl* /*aDestination*/) + { + if (iAlarmAlertServer) + { + iAlarmAlertServer->HandleSwitchOnEvent(); + } + } + +void CEikServAppUi::HandleSystemEventL(const TWsEvent& aEvent) + { + TInt event = *((TInt*)aEvent.EventData()); + switch (event) + { +#ifdef _DEBUG + case EEikServExit: + CBaActiveScheduler::Exit(); + break; +#endif + case EEikServChangePasswordMode: + // No action in Avkon + break; + case EEikServShowTaskList: + LaunchTaskListL(); + break; + case EEikServHideTaskList: + CloseTaskList(); + break; + default: + break; + } + } + +CEikServAppUi::~CEikServAppUi() + { + if (iAknAnimKeySound) + { + iAknAnimKeySound->Close(); + } + delete iAknAnimKeySound; + + if (iAknAnimDll) + { + iAknAnimDll->Close(); + } + delete iAknAnimDll; + + // Shut down the key sound server. + RKeySoundServerCloser ksCloserSession; + ksCloserSession.CloseServer(); + + iOffScreenGroupWin.Close(); + delete iAppbarWindow; + delete iSidebarWindow; + + if (iCoeEnv) + { + iCoeEnv->DeleteResourceFile(iResourceFileOffset); + } + + delete iIdler; + iNotifServerAppQueue.Close(); + + delete iNotifierController; + delete iNotifierDialogController; + } + +MEikServAlarm* CEikServAppUi::NewAlarmL(CEikAlmControlSupervisor& aSupervisor) + { + CEikAlarmControl* alarm = new(ELeave) CEikAlarmControl(&aSupervisor,this); + CleanupStack::PushL(alarm); + alarm->ConstructL(); + CleanupStack::Pop(); // alarm + return alarm; + } + +void CEikServAppUi::EnsureExternalKeyHandlerAppStreamExistsL() + { + } + +// Respond to an out of memory event from the window server. +void CEikServAppUi::HandleOomEvent() + { + TBuf<80> msg1; + TBuf<80> msg2; + iEikonEnv->ReadResource(msg1, R_EIKSRV_OOM_EVENT_TOP); + iEikonEnv->ReadResource(msg2, R_EIKSRV_OOM_EVENT_BOT); + MEikAlertWin* mAlert = CONST_CAST(MEikAlertWin*, iEikonEnv->Alert()); + CEikDialog* alert = mAlert->AsEikDialog(); + + CEikMover* title = NULL; + if ( alert ) + { + title = &( alert->Title() ); + alert->SetGloballyCapturing(ETrue); + title->SetActive(EFalse); + } + iEikonEnv->AlertWin(msg1, msg2); + if ( alert ) + { + title->SetActive(ETrue); + alert->SetGloballyCapturing(EFalse); + } + } + +// Respond to an error from the backlight (battery too low). +void CEikServAppUi::HandleBacklightError(TInt /*aError*/) + { + } + +// Respond to a logging error from wserv (for use by developers) +void CEikServAppUi::HandleWservLoggingError(TInt aError) + { + TBuf<80> temp; + iEikonEnv->ReadResource(temp, R_EIKSRV_WSERV_LOGGING_ERROR); + TBuf<80> msg; + msg.Format(temp, aError); + iEikonEnv->AlertWin(msg); + } + +EXPORT_C void CEikServAppUi::SuppressAppSwitching(TBool aSuppress) + { + // Ignore error as there is nothing to do if failing. + iAknCapServerClient.ConnectAndSendAppsKeySuppress(aSuppress); + } + +HBufC* CEikServAppUi::ConstructPanicTextLC( RThread& aThread, TBool aRDSupport ) const + { + HBufC* panicText = HBufC::NewLC( KEikServPanicTextBufferSize ); + TPtr ptr = panicText->Des(); + + iEikonEnv->ReadResource( ptr, R_PROGRAM_CLOSED ); + + ptr.Append( '\n' ); + + HBufC* buffer = aThread.Name().AllocL(); + TPtr name = buffer->Des(); + + // Here we truncate the thread name to fit in the second and third lines of the note. + + TRect mainPane; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EPopupParent, mainPane ); + TAknLayoutRect popupNoteWindow; + + AknLayoutUtils::TAknCbaLocation cbaLocation( AknLayoutUtils::CbaLocation() ); + TInt variety( 0 ); + if ( cbaLocation == AknLayoutUtils::EAknCbaLocationRight ) + { + variety = 3; + } + else if ( cbaLocation == AknLayoutUtils::EAknCbaLocationLeft ) + { + variety = 6; + } + else + { + variety = 0; + } + + popupNoteWindow.LayoutRect(mainPane, AknLayoutScalable_Avkon::popup_note_window( variety ) ); + + TAknLayoutText textRectTwoLines; + + textRectTwoLines.LayoutText( + popupNoteWindow.Rect(), + AKN_LAYOUT_TEXT_Note_pop_up_window_texts_Line_1(1)); + + // First determine how much fits in the 2. line of the note this can't return NULL. + const CFont* font = textRectTwoLines.Font(); + + TInt characters( font->TextCount( name, textRectTwoLines.TextRect().Width() ) ); + + // 'characters' is now the amount of characters that fit in the second line. + + ptr.Append( name.Left( characters ) ); + ptr.Append( '\n' ); + + // If the name was cut, clip the rest in the third line. + TInt charactersLeft( name.Length() - characters ); + + if ( charactersLeft > 0 ) + { + TPtr line3( + (TText*)&name[characters], + charactersLeft, + charactersLeft ); + + popupNoteWindow.LayoutRect( + mainPane, + AknLayoutScalable_Avkon::popup_note_window( variety + 1) ); + + TAknLayoutText textRectThreeLines; + + textRectThreeLines.LayoutText( + popupNoteWindow.Rect(), + AKN_LAYOUT_TEXT_Note_pop_up_window_texts_Line_1(2)); + + // No bidirectional text support for rendering the thread name. This is intentional. + + AknTextUtils::ClipToFit( + line3, + *font, + textRectThreeLines.TextRect().Width() ); + + ptr.Append( line3 ); + ptr.Append( '\n' ); + } + + delete buffer; + + // Append panic category and reason only if RD-support file exists. + + if ( aRDSupport ) + { + ptr.Append( aThread.ExitCategory() ); + ptr.Append( ' ' ); + ptr.AppendNum( aThread.ExitReason() ); + } + + return panicText; + } + +void CEikServAppUi::LoadBitmapCursorsL() + { + RWsSession& ws = iEikonEnv->WsSession(); + + // Create the array containing one sprite member. + TFixedArray spriteMemberArray; + TSpriteMember& spriteMember = spriteMemberArray[0]; + spriteMember.iInterval = TTimeIntervalMicroSeconds32(0); + + // This resource is of type AVKON_CUSTOM_TEXT_CURSORS defined in eiksrvui.rss. + TResourceReader reader; + iEikonEnv->CreateResourceReaderLC(reader, R_AKN_CUSTOM_TEXT_CURSORS); + + HBufC* bmpFile = reader.ReadHBufCL(); + CleanupStack::PushL(bmpFile); + + + TInt count = reader.ReadInt16(); + for (TInt ii = 0; ii < count; ii++) + { + // id + TInt id = reader.ReadInt32(); + + // bmpId and maskId + TInt bmpId = reader.ReadInt32(); + TInt maskId = reader.ReadInt32(); + spriteMember.iBitmap = NULL; + spriteMember.iMaskBitmap = NULL; + + if (maskId != -1) + { + AknIconUtils::CreateIconLC( + spriteMember.iBitmap, + spriteMember.iMaskBitmap, + *bmpFile, + bmpId, + maskId ); + } + else + { + spriteMember.iBitmap = AknIconUtils::CreateIconL( *bmpFile, bmpId ); + CleanupStack::PushL( spriteMember.iBitmap ); + } + + TAknWindowLineLayout l; + + switch( id ) + { + case KAknCustomTextCursorIdLeftToRight: + case KAknCustomTextCursorIdRightToLeft: + l = AknLayoutScalable_Avkon::cursor_primary_pane().LayoutLine(); + break; + case KAknCustomTextCursorIdLeftToRightThin: + case KAknCustomTextCursorIdRightToLeftThin: + default: + l = AknLayoutScalable_Avkon::cursor_primary_small_pane().LayoutLine(); + break; + } + + TRect rectParent = ApplicationRect(); + TAknLayoutRect layoutRect; + layoutRect.LayoutRect( rectParent, l ); + TRect rectCursorBitmap( layoutRect.Rect() ); + TSize scaledSize(rectCursorBitmap.Width(), rectCursorBitmap.Height() ); + + // Perform the scaling + AknIconUtils::SetSize( + spriteMember.iBitmap, + scaledSize, + EAspectRatioPreservedAndUnusedSpaceRemoved); + + if ( spriteMember.iMaskBitmap ) + { + AknIconUtils::SetSize( + spriteMember.iMaskBitmap, + scaledSize, + EAspectRatioPreservedAndUnusedSpaceRemoved); + } + + // Flags. + TUint flags = reader.ReadUint16(); + spriteMember.iInvertMask = flags|EAknCustomTextCursorFlagInvertMask; + + // Draw mode. + spriteMember.iDrawMode = (CGraphicsContext::TDrawMode)reader.ReadInt16(); + + // Offset. Use actual scalings used. Do not read inside TPoint constructor for compiler + // independence. + TInt offsetX = reader.ReadInt16(); + TInt offsetY = reader.ReadInt16(); + spriteMember.iOffset = TPoint(offsetX, offsetY); + + // Alignment. + TInt align = reader.ReadInt16(); + + // Decode the "vehicle ids" into features: + TAknFontCategory category(EAknFontCategoryPrimary); + TBool isRightToLeft(EFalse); + + switch( id ) + { + case KAknCustomTextCursorIdLeftToRight: + break; + case KAknCustomTextCursorIdRightToLeft: + isRightToLeft = ETrue; + break; + case KAknCustomTextCursorIdLeftToRightThin: + category = EAknFontCategoryPrimarySmall; + break; + case KAknCustomTextCursorIdRightToLeftThin: + category = EAknFontCategoryPrimarySmall; + isRightToLeft = ETrue; + break; + default: + // Should not get here if the resource is correct. Already initialized defaults + // get used. + break; + } + + id = AknCustomCursorSupport::CustomBidiTextCursorId( + category, + rectCursorBitmap, + isRightToLeft ); + + // Return code is ignored since we will regularly be setting a bitmap twice + (void)ws.SetCustomTextCursor( + id, + spriteMemberArray.Array(), + ESpriteFlash, + (RWsSession::TCustomTextCursorAlignment)align); + + if (maskId != -1) + { + CleanupStack::PopAndDestroy(spriteMember.iMaskBitmap); + } + CleanupStack::PopAndDestroy(spriteMember.iBitmap); + } + + CleanupStack::PopAndDestroy(bmpFile); + CleanupStack::PopAndDestroy(); // reader + } + +// +// First export +// + +EXPORT_C CEikServAppUi* CreateAppUi() + { + return new CEikServAppUi; + } + +EXPORT_C void CEikServAppUi::ActivateDisplayIfNeeded() + { +#ifndef __WINS__ + + // Check if screen saver active. + TApaTaskList list(iCoeEnv->WsSession()); + TApaTask task = list.FindByPos(0); // topmost application + CApaWindowGroupName* name = 0; + TRAPD( err, name = CApaWindowGroupName::NewL(iCoeEnv->WsSession(), task.WgId())); + if ( !err && name->AppUid() == TUid::Uid(0x100056CF) ) // Screen saver Uid + { + User::ResetInactivityTime(); + } + delete name; +#endif + } + +EXPORT_C CEikServAppUiSession* CEikServAppUi::CreateSessionL( /*RThread aClient*/ ) + { + return CAknEikServAppUiSession::NewL( /*aClient,*/ this, *this); + } + +void CEikServAppUi::Extension(TUid aExtensionUid, const TDesC8& aBuffer, RMessagePtr2 aMessage) + { + TBool hasCap = aMessage.HasCapability(ECapabilityWriteDeviceData); // Write Dev D required here + + if (!hasCap) + { + aMessage.Complete(KErrPermissionDenied); + return; + } + + switch(aExtensionUid.iUid) + { + case EAknCommonNotifierServerRunning: + { + aMessage.Complete(KErrNone); + TRAP_IGNORE( + // Do not clear the list, it can be used when common notifier server is being + // restarted due crash. + for (TInt i = iNotifierController->iPreloadList.Count() - 1; i >= 0; i--) + { + iNotifierController->iPreloadList[i]->PreLoadLibraryL(); + } + ); + break; + } + case EAknNotifierControllerCmd: + { + TInt cmd = static_cast(*(aBuffer.Ptr())); +#ifdef _DEBUG + RThread thread; + aMessage.ClientL(thread); // ok to leave in debug mode + TName threadName( thread.Name() ); +#endif + if(cmd == CAknNotifierControllerUtility::EDoAllow) + { +#ifdef _DEBUG + + RDebug::Print(_L("Allow all notifications: thread %S"), &threadName); +#endif + NotifierController()->DoAllowNotifications(); + } + else if(cmd == CAknNotifierControllerUtility::EDoStop) + { +#ifdef _DEBUG + RDebug::Print(_L("Stop all notifications: thread %S"), &threadName); +#endif + NotifierController()->DoStopNotifications(); + } + else if(cmd == CAknNotifierControllerUtility::DoCancelAll) + { +#ifdef _DEBUG + RDebug::Print(_L("Cancel all notifications: thread %S"), &threadName); +#endif + CloseTaskList(); + NotifierController()->DoCancelAllNotificatons(); + } + else + { + if (!aMessage.IsNull()) + { + aMessage.Complete(KErrNotSupported); + } + return; + } + + if (!aMessage.IsNull()) + { + // Release caller before forwarding to app servers. + aMessage.Complete(KErrNone); + } + + NotifierController()->NotifyAppServers(cmd); + break; + } + case EAknCapServerStartupComplete: + { + aMessage.Complete(KErrNone); // No one is listening this return value. + TRAP_IGNORE(DoAknCapServerStartupCompleteL()); + break; + } + case EAknSignalAknCapServerReady: + { + DoSignalWhenAknServerReady(aMessage); // Completes message when akncapserver is ready. + break; + } + default: + aMessage.Complete(KErrNotSupported); + } + } + +/// Session within avkon code: + +CAknEikServAppUiSession::CAknEikServAppUiSession( + /* RThread aClient, */ + MEikServAppUiSessionHandler* aHandler, + CEikServAppUi& aAppUi ) +: CEikServAppUiSession( aHandler), iAppUi(aAppUi) + { + } + +CAknEikServAppUiSession* CAknEikServAppUiSession::NewL( + /*RThread aClient, */ + MEikServAppUiSessionHandler* aHandler, + CEikServAppUi& aAppUi ) + { + CAknEikServAppUiSession* session = new(ELeave) CAknEikServAppUiSession( + /*aClient,*/ + aHandler, + aAppUi); + + CleanupStack::PushL(session); + session->ConstructL(); + CleanupStack::Pop(); + return session; + } + +CAknEikServAppUiSession::~CAknEikServAppUiSession() + { + } + +void CAknEikServAppUiSession::ConstructL() + { + } + +void CAknEikServAppUiSession::ServiceL(const RMessage2 &aMessage) + { + switch (aMessage.Function()) + { + case EEikAppUiNotifyAlarmServerOfTaskChange: + SessionHandler()->NotifyAlarmServerOfTaskChangeL(); + aMessage.Complete(KErrNone); + break; + case EEikAppUiEnableTaskList: + SessionHandler()->EnableTaskListL(); + aMessage.Complete(KErrNone); + break; + case EEikAppUiLaunchTaskList: + SessionHandler()->LaunchTaskListL(); + aMessage.Complete(KErrNone); + break; + case EEikAppUiCycleTasks: + { + aMessage.Complete(KErrNone); + } + break; + case EAknEikAppUiAddToStack: + { + CCoeControl*temp = REINTERPRET_CAST(CCoeControl*, CONST_CAST(TAny*, aMessage.Ptr0()) ); + iAppUi.AddToStackL(temp, aMessage.Int1(), aMessage.Int2()); + aMessage.Complete(KErrNone); + } + break; + case EAknEikAppUiRemoveFromStack: + { + CCoeControl*temp = REINTERPRET_CAST(CCoeControl*, CONST_CAST(TAny*, aMessage.Ptr0()) ); + iAppUi.RemoveFromStack(temp); + aMessage.Complete(KErrNone); + } + break; + case EAknEikAppUiShutdownApps: + { + aMessage.HasCapabilityL(ECapabilityPowerMgmt); // PowerMgmt required here + TUid uid; + uid.iUid = (REINTERPRET_CAST(TInt, CONST_CAST(TAny*, aMessage.Ptr0()) )); + TInt timeout = REINTERPRET_CAST(TInt, CONST_CAST(TAny*, aMessage.Ptr1()) ); + + //ShutdownAppsL must complete message. + TRAPD(err, iAppUi.ShutdownAppsL(uid, aMessage, timeout)); + if (err != KErrNone) + { + // Message wasn't completed. + aMessage.Complete(err); + } + } + break; + + default: + { + // It is the base class' responsibility to complete. + // This will pick up any new opcodes added by Symbian that are + // not yet handled here. + CEikServAppUiSession::ServiceL(aMessage); + break; + } + } + } +void CAknEikServAppUiSession::Write(const RMessage2& aMessage, const TAny* aPtr, const TDesC8& aDes, + TInt anOffset) + { + TRAPD(ret, aMessage.WriteL( (TInt)aPtr, aDes, anOffset);) + if (ret != KErrNone) + { + RThread clientThread; + (void)aMessage.Client( clientThread); + clientThread.Panic(_L("CEikServAppUi server"), KErrGeneral); + } + } + +// +// Main +// + +GLDEF_C TInt PanicNoteThreadFunction( TAny* /*aParameters*/ ) + { + return KErrNone; + } + +// Probably obsolete, but just in case, Fix Me !! +EXPORT_C void CEikServAppUi::HideApplicationFromFswL(TInt aUid,TBool aDisable) + { + iAknCapServerClient.HideApplicationFromFsw(aDisable, aUid); + } + +// Start new notifier server plugin using fixed server differentiator. +void StartNotifierAppServerL(TUid aAppServerUid) + { + RApaLsSession apa; + User::LeaveIfError(apa.Connect()); + CleanupClosePushL(apa); + + TApaAppInfo info; + + TInt err(0); + for(TInt i = 20; + ((err = apa.GetAppInfo(info, aAppServerUid)) == RApaLsSession::EAppListInvalid) && i > 0; + i--) + { + User::After(500000); + } + + User::LeaveIfError(err); + + CApaCommandLine* cmdLine = CApaCommandLine::NewLC(); + cmdLine->SetExecutableNameL(info.iFullName); + cmdLine->SetServerRequiredL(KUikonUidPluginInterfaceNotifiers); + cmdLine->SetCommandL(EApaCommandBackground); + TThreadId dummy; + User::LeaveIfError(apa.StartApp(*cmdLine, dummy)); + + CleanupStack::PopAndDestroy(2, &apa); // cmdLine and apa + } + +TBool StartNotifierAppServer(TAny* aAny) + { + // Resolve uid. + CEikServAppUi* appUI = (CEikServAppUi*)aAny; + TUid serverUid = appUI->NextNotifierServerUid(); + + // Check if the aknnfysrv.exe is running, perventing for dropping into + // an infinite loop of launching aknnfysrv.exe + if (serverUid == KCommonNotifierAppSrvUid) + { + TFullName serverName; + serverName.Format(_L("%08x_%08x_AppServer"), KUikonUidPluginInterfaceNotifiers, KCommonNotifierAppSrvUid); + TFindServer find(serverName); + TFullName fullName; + if (find.Next(fullName) == KErrNone) + { + // Aknnfysrv.exe is already running, so just return. + return EFalse; + } + } + + if (serverUid != KNullUid) + { + TRAP_IGNORE(StartNotifierAppServerL(serverUid)) + } + + return EFalse; // do not call back again + } + +EXPORT_C void CEikServAppUi::StartNewServerApplicationL(TUid aAppServerUid) + { + // Add to queue. + if (iNotifServerAppQueue.Find(aAppServerUid.iUid) == KErrNotFound) + { + iNotifServerAppQueue.AppendL(aAppServerUid.iUid); + } + + // Start idler if does not exist (if only akncapserver is already running). + if (!iIdler && iAknCapServerClient.Handle() != 0) + { + iIdler = CIdle::NewL(CActive::EPriorityHigh); + iIdler->Start(TCallBack(StartNotifierAppServer, this)); + } + } + +TUid CEikServAppUi::NextNotifierServerUid() + { + TInt uid = 0; + + delete iIdler; + iIdler = 0; + + if (iNotifServerAppQueue.Count()) + { + uid = iNotifServerAppQueue[0]; + iNotifServerAppQueue.Remove(0); + } + + // Activate idler for next uid. + if (iNotifServerAppQueue.Count()) + { + // We must trap this call, if creating a new CIdle fails, no applications will be started + // from queue until new request comes. + TRAPD(err, iIdler = CIdle::NewL(CActive::EPriorityHigh)) + if (!err) + { + iIdler->Start(TCallBack(StartNotifierAppServer, this)); + } + } + else + { + // Last notifier app server is being launched, free starter. + if (!iAknCapServerMessage.IsNull()) + { + iAknCapServerMessage.Complete(KErrNone); + } + } + + // Return uid of topmost. + return TUid::Uid(uid); + } + +void CEikServAppUi::UpdateCursorsL() + { + LoadBitmapCursorsL(); + } + +TInt DoPollCapServer(TAny* appui) + { + _LIT(KServerNameFormat, "%08x_%08x_AppServer"); + TFullName serverName; + serverName.Format(KServerNameFormat, KUikonUidPluginInterfaceNotifiers, KAknCapServerUid.iUid); + TFindServer find(serverName); + TFullName fullName; + ((CEikServAppUi*)appui)->AknCapServerStartupComplete(find.Next(fullName) == KErrNone); + return KErrNone; + } + +// We are doing this on startup when there is always enough memory, so methods with L really +// can't leave. +void CEikServAppUi::AknCapServerStartupComplete(TBool aComplete) + { + delete iIdler; + iIdler = 0; + + if (aComplete) + { + // In this phase of boot, create real connection to akncapserver. + iAknCapServerClient.DoEikonServerConnect(); + + // Create alarm server as we have capserver running. + TRAPD(err, DoAlarmServerStartupL()); + + // No use to startup phone if this fails. + __ASSERT_ALWAYS(!err, User::Invariant()); + + iIdler = CIdle::NewL(CActive::EPriorityHigh); + iIdler->Start(TCallBack(StartNotifierAppServer, this)); + } + else + { + const TInt waitDelay = 200000; // 0.2 seconds + User::After(waitDelay); + DoAknCapServerStartupCompleteL(); + } + } + +void CEikServAppUi::DoAknCapServerStartupCompleteL() + { + __ASSERT_DEBUG(iIdler == 0, User::Invariant()); + + iIdler = CIdle::NewL(CActive::EPriorityIdle); + iIdler->Start(TCallBack(DoPollCapServer, this)); + } + +void CEikServAppUi::DoSignalWhenAknServerReady(const RMessagePtr2& aMessage) + { + if (iAknCapServerClient.Handle() != 0) + { + aMessage.Complete(KErrNone); + } + + // This should be used as single shot. + __ASSERT_DEBUG(iAknCapServerMessage.IsNull(), User::Invariant()); + iAknCapServerMessage = aMessage; + } + +void CEikServAppUi::DoAlarmServerStartupL() + { + // Stupid naming, perhaps. + iAlarmAlertServer = CEikServAlarmAlertServer::NewL(this); + + // Start AlarmServer. + TInt err = AlarmClientUtils::StartAlarmServer(); + if (err != KErrNone && err != KErrAlreadyExists) + { + User::Leave(err); + } + + HandleSwitchOnEventL( NULL ); + } + +// End of file