src/hbservers/hbdevicedialogappserver/main.cpp
changeset 1 f7ac710697a9
parent 0 16d8024aca5e
child 3 11d3954df52a
--- a/src/hbservers/hbdevicedialogappserver/main.cpp	Mon Apr 19 14:02:13 2010 +0300
+++ b/src/hbservers/hbdevicedialogappserver/main.cpp	Mon May 03 12:48:33 2010 +0300
@@ -36,54 +36,125 @@
 #include <aknappui.h>
 #include <eikenv.h>
 #include <apgwgnam.h>
+#include <hbdevicedialogserverdefs_p.h>
+#include "hbddappfactorysymbian.h"
 #endif // Q_OS_SYMBIAN
 
-// QApplication calls RProcess::Rendezvous() before server has been created.
-// Semaphores are signaled when server initialization is done.
 #if defined (Q_OS_SYMBIAN)
-static void SignalClientSemaphores()
+class Lock
 {
-    // Initialisation complete, now signal client(s)
-    _LIT(KFindPattern, "hbdevdlgcli_?*");
-    TFindSemaphore find(KFindPattern);
-    RSemaphore sema;
-    TFullName findResult;
-    while(find.Next(findResult) == KErrNone) {
-        sema.Open(find);
-        sema.Signal();
-        sema.Close();
+public:
+    enum State {
+        Reserved,
+        Acquired,
+        Error
+    };
+    Lock();
+    ~Lock(){close();}
+    void close(){mFile.Close(); mFs.Close();}
+    State acquire();
+    static bool serverExists();
+
+private:
+    RFs mFs;
+    RFile mFile;
+};
+
+Lock::Lock()
+{
+    // Using a file for interprocess lock
+    const int NumMessageSlots = 1;
+    if (mFs.Connect(NumMessageSlots) == KErrNone) {
+        mFs.CreatePrivatePath(EDriveC);
+        if (mFs.SetSessionToPrivate(EDriveC) == KErrNone) {
+            _LIT(KFileName, "lockFile");
+            const TUint mode = EFileShareReadersOrWriters;
+            if (mFile.Create(mFs, KFileName, mode) == KErrAlreadyExists) {
+                mFile.Open(mFs, KFileName, mode);
+            }
+        }
     }
 }
+
+// Try to acquire lock
+Lock::State Lock::acquire()
+{
+    State state = Error;
+    // If process holding the lock crashes, file server releases the lock
+    if (mFile.SubSessionHandle()) {
+        TInt error = mFile.Lock(0, 1);
+        if (error == KErrNone) {
+            state = Acquired;
+        } else if (error == KErrLocked) {
+            state = Reserved;
+        }
+    }
+    return state;
+}
+
+// Check if Symbian server exists
+bool Lock::serverExists()
+{
+    TFindServer findHbServer(KHbServerName);
+    TFullName name;
+    return findHbServer.Next(name) == KErrNone;
+}
+
 #endif // Q_OS_SYMBIAN
 
+#define USE_LOCKER 1
 int main(int arg, char *args[])
 {
     INSTALL_MESSAGE_HANDLER
 
 #if defined (Q_OS_SYMBIAN)
     // Guard against starting multiple copies of the server
-    RSemaphore serverExistsSema;
-    _LIT(KSemaName, "hbdevdlgsrv");
-    TInt error = serverExistsSema.CreateGlobal(KSemaName, 0);
-    if (error != KErrNone) {
-        RProcess::Rendezvous(error);
-        return error;
+    Lock lock;
+    Lock::State lockState;
+    for(;;) {
+        lockState = lock.acquire();
+        if (lockState == Lock::Acquired) {
+            break;
+        } else if (lockState == Lock::Reserved) {
+            // Process may be starting, wait for server object to be created
+            if (Lock::serverExists()) {
+                break;
+            } else {
+                const TInt KTimeout = 100000; // 100 ms
+                User::After(KTimeout);
+            }
+        } else {
+            break;
+        }
     }
+    if (lockState != Lock::Acquired) {
+        // With KErrAlreadyExists client should try to connect, otherwise bail out.
+        RProcess::Rendezvous(lockState == Lock::Reserved ? KErrAlreadyExists:KErrGeneral);
+        return KErrNone;
+    }
+    _LIT(KThreadName, "hbdevdlgsrvapp");
+    RThread().RenameMe(KThreadName); // nicer panic info
+
+    HbApplication app(deviceDialogAppFactory, arg, args, Hb::NoSplash);
+#else // Q_OS_SYMBIAN
+    HbApplication app(arg, args);
 #endif // Q_OS_SYMBIAN
 
-    HbApplication app(arg, args, Hb::NoSplash);
-
-    //QTranslator translator;
-    //QString lang_id = QLocale::system().name();
-    //translator.load(path_to + "common_" + lang_id);
-    //app.installTranslator(&translator);
-
     HbView* view = new HbView;
     view->hideItems(Hb::AllItems);
     view->setContentFullScreen();
 
-    // Workaround to get device dialogs visible until transparency works
-    HbMainWindow mainWindow(0); //, Hb::WindowFlagTransparent);
+    HbMainWindow mainWindow(0, Hb::WindowFlagTransparent);
+        
+#if defined (Q_OS_SYMBIAN)
+    CCoeControl *c = mainWindow.effectiveWinId();
+    RWindow *rw = static_cast<RWindow*>(c->DrawableWindow());
+    rw->SetRequiredDisplayMode( EColor16MA );
+    TInt err = rw->SetTransparencyAlphaChannel();
+    if ( err == KErrNone ) {
+        rw->SetBackgroundColor(~0);
+    }
+#endif // Q_OS_SYMBIAN
 
     HbTransparentWindow *transparentWindow = new HbTransparentWindow;
     HbStackedLayout *stackedLayout = new HbStackedLayout;
@@ -92,32 +163,31 @@
 
     mainWindow.addView(view);
 
-    HbDeviceDialogServer server;
-    server.setMainWindow(&mainWindow);
-
 #if defined (Q_OS_SYMBIAN)
     CEikonEnv* env = CEikonEnv::Static();
 
-    if ( env )
-        {
+    if (env) {
         CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC(env->WsSession());
         wgName->SetHidden(ETrue); // hides us from FSW and protects us from OOM FW etc.
         wgName->SetSystem(ETrue); // Allow only application with PowerManagement cap to shut us down
         wgName->SetCaptionL(_L("HbDeviceDialogAppServer"));
         wgName->SetAppUid(KNullUid);
         wgName->SetWindowGroupName(env->RootWin());
-        CleanupStack::PopAndDestroy();
+        CleanupStack::PopAndDestroy();       
+    }
+#endif // Q_OS_SYMBIAN
 
-        }
-    SignalClientSemaphores();
+    // HbApplication must be created before the server to have environment ready
+    HbDeviceDialogServer server;
+    server.setMainWindow(&mainWindow);
+
+#if defined (Q_OS_SYMBIAN)
+    // Server is created, client may connect
+    RProcess::Rendezvous(KErrNone);
 #endif // Q_OS_SYMBIAN
 
     int returnValue = app.exec();
 
-#if defined (Q_OS_SYMBIAN)
-    serverExistsSema.Close();
-#endif // Q_OS_SYMBIAN
-
     UNINSTALL_MESSAGE_HANDLER
 
     return returnValue;