epoc-appfocus.cpp

Go to the documentation of this file.
00001 /*
00002  !concept {:name => "Tracking application focus on Symbian"}
00003 */
00004 
00005 #include "epoc-appfocus.hpp"
00006 
00007 #if __APPFOCUS_ENABLED__
00008 
00009 #include "application_config.h"
00010 #include "er_errors.h"
00011 #include "sa_sensor_list_log_db.h"
00012 
00013 #include "common/assertions.h"
00014 #include "common/error_list.h"
00015 #include "common/logging.h"
00016 #include "common/platform_error.h"
00017 #include "common/utilities.h"
00018 
00019 #include <apgwgnam.h> // library apgrfx.lib
00020 #include <coedef.h> // for ECoeWinPriorityNeverAtFront
00021 
00022 // A useful reference is http://developer.sonyericsson.com/message/99028.
00023 
00024 // ----------------------------------------------------------------------------
00025 
00026 NONSHARABLE_CLASS(CMyWindowGroup) :
00027   public CBase
00028 {
00029  public:
00030 
00031   static CMyWindowGroup* NewL(RWsSession& aWsSession);
00032 
00033   virtual ~CMyWindowGroup();
00034 
00035   RWindowGroup& Ref() { return iWindowGroup; }
00036 
00037  private:
00038 
00039   CMyWindowGroup(RWsSession& aWsSession) : iWsSession(aWsSession), iWindowGroup(aWsSession) {}
00040 
00041   void ConstructL();
00042 
00043  private:
00044 
00045   RWsSession& iWsSession;
00046 
00047   DEF_SESSION(RWindowGroup, iWindowGroup);
00048 };
00049 
00050 CMyWindowGroup* CMyWindowGroup::NewL(RWsSession& aWsSession)
00051 {
00052   CMyWindowGroup* obj = new (ELeave) CMyWindowGroup(aWsSession);
00053   CleanupStack::PushL(obj);
00054   obj->ConstructL();
00055   CleanupStack::Pop();
00056   return obj;
00057 }
00058 
00059 void CMyWindowGroup::ConstructL()
00060 {
00061   TUint32 clientHandle = reinterpret_cast<TUint32>(&iWindowGroup);
00062   LEAVE_IF_ERROR_OR_SET_SESSION_OPEN(iWindowGroup, iWindowGroup.Construct(clientHandle, EFalse));
00063 
00064   // Hide the icon for this window group. Not sure exactly what it
00065   // takes to do this, but all of this (in this order) at least
00066   // appears to work. People have been having trouble making this
00067   // happen, it seems. Probably they get this right with the PyS60
00068   // keycapture module, but have not checked.
00069   CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC(iWsSession, clientHandle);
00070   wgName->SetHidden(ETrue);
00071   CleanupStack::PopAndDestroy(); // wgName
00072 
00073   iWindowGroup.EnableReceiptOfFocus(EFalse);
00074   iWindowGroup.SetOrdinalPosition(-1, ECoeWinPriorityNeverAtFront); // hide the window group
00075   iWindowGroup.DefaultOwningWindow();
00076 }
00077 
00078 CMyWindowGroup::~CMyWindowGroup()
00079 {
00080   SESSION_CLOSE_IF_OPEN(iWindowGroup);
00081 }
00082 
00083 // ----------------------------------------------------------------------------
00084 
00085 CSensor_appfocus* CSensor_appfocus::NewL(LogDb* aLogDb)
00086 {
00087   CSensor_appfocus* obj = new (ELeave) CSensor_appfocus(aLogDb);
00088   CleanupStack::PushL(obj);
00089   obj->ConstructL();
00090   CleanupStack::Pop();
00091   return obj;
00092 }
00093 
00094 CSensor_appfocus::CSensor_appfocus(LogDb* aLogDb) : 
00095   CActiveRunG(EPriorityStandard)
00096 {
00097   iLogDb = aLogDb;
00098   CActiveScheduler::Add(this);
00099 }
00100 
00101 void CSensor_appfocus::ConstructL()
00102 {
00103   LEAVE_IF_ERROR_OR_SET_SESSION_OPEN(iWsSession, iWsSession.Connect());
00104 
00105   // It seems the RWsSession passed to RWindowGroup must be open, so
00106   // we require some contortions here.
00107   iMyWindowGroup = CMyWindowGroup::NewL(iWsSession);
00108 }
00109 
00110 CSensor_appfocus::~CSensor_appfocus()
00111 {
00112   Cancel(); // safe when AO inactive as DoCancel not called
00113   delete iMyWindowGroup;
00114   SESSION_CLOSE_IF_OPEN(iWsSession);
00115 }
00116 
00117 gboolean CSensor_appfocus::StartL(GError** error)
00118 {
00119   if (!iFocusChangeEventsEnabled) {
00120     // I do not believe it's dangerous to leave this enabled, if say
00121     // there is a scanning error and we cannot continue processing
00122     // events. We do not invoke EventReady, and so the event delivery
00123     // should skip us. I hope.
00124     User::LeaveIfError(iMyWindowGroup->Ref().EnableFocusChangeEvents());
00125     iFocusChangeEventsEnabled = ETrue;
00126   }
00127   if (!IsActive()) {
00128     MakeRequest();
00129     //log_db_log_status(iLogDb, NULL, "appfocus sensor started");
00130   }
00131   return TRUE;
00132 }
00133 
00134 void CSensor_appfocus::Stop()
00135 {
00136   if (IsActive()) {
00137     Cancel();
00138     //log_db_log_status(iLogDb, NULL, "appfocus sensor stopped");
00139   }
00140 
00141   if (iFocusChangeEventsEnabled) {
00142     // Okay to call even if not enabled.
00143     iMyWindowGroup->Ref().DisableFocusChangeEvents();
00144     iFocusChangeEventsEnabled = EFalse;
00145   }
00146 }
00147 
00148 void CSensor_appfocus::MakeRequest()
00149 {
00150   // I guess we do actually require our very own window server session
00151   // here.
00152   iWsSession.EventReady(&iStatus);
00153 
00154   SetActive();
00155 }
00156 
00157 gboolean CSensor_appfocus::RunGL(GError** error)
00158 {
00159   assert_error_unset(error);
00160 
00161   TInt errCode = iStatus.Int();
00162 
00163   //logg("appfocus event %d", errCode);
00164 
00165   //Leave(gx_error_no_memory); // test
00166 
00167   if (errCode) {
00168     // This error really should not occur, but since it has, we will
00169     // simply stop this one scanner. For a retry, someone just call
00170     // StartL.
00171     goto fail;
00172   } else {
00173     // Must do a GetEvent before doing another EventReady.
00174     TWsEvent event;
00175     iWsSession.GetEvent(event);
00176 
00177     TInt wgid = iWsSession.GetFocusWindowGroup();
00178     CApaWindowGroupName* gn = NULL;
00179     TRAP(errCode, gn = CApaWindowGroupName::NewL(iWsSession, wgid));
00180     if (errCode) {
00181       goto fail;
00182     }
00183     TUid uid = gn->AppUid(); // the uid of the focused app
00184     TInt32 appUid = uid.iUid;
00185     sqlite3_int64 appUid64 = (sqlite3_int64)((TUint32)appUid);
00186     TPtrC nameDes = gn->Caption();
00187     gchar appName[32+1]; // should be big enough for informative logging
00188     ConvToUtf8CString(appName, 32, nameDes);
00189     delete gn;
00190     
00191     guilogf("appfocus: '%s' 0x%08x", appName, appUid);
00192 
00193     if (!log_db_log_appfocus(iLogDb, appUid64, appName, error)) {
00194       return FALSE;
00195     }
00196 
00197     MakeRequest();
00198   }
00199 
00200   return TRUE;
00201 
00202  fail:
00203   if (!log_db_log_status(iLogDb, error, "INACTIVATE: appfocus: failure reading sensor: %s (%d)", plat_error_strerror(errCode), errCode)) {
00204     // Logging failing is quite severe. We shall report the error
00205     // upwards, where the framework will hopefully take corrective
00206     // action, and probably then call either our StartL or dtor,
00207     // depending on whether recovery was possible.
00208     return FALSE;
00209   }
00210 
00211   return TRUE;
00212 }
00213 
00214 const char* CSensor_appfocus::Description()
00215 {
00216   return "appfocus";
00217 }
00218 
00219 void CSensor_appfocus::DoCancel()
00220 {
00221   iWsSession.EventReadyCancel();
00222 }
00223 
00224 #endif // __APPFOCUS_ENABLED__
00225 
00226 /**
00227 
00228 epoc-appfocus.cpp
00229 
00230 Copyright 2009 Helsinki Institute for Information Technology (HIIT)
00231 and the authors. All rights reserved.
00232 
00233 Authors: Tero Hasu <tero.hasu@hut.fi>
00234 
00235 Permission is hereby granted, free of charge, to any person
00236 obtaining a copy of this software and associated documentation files
00237 (the "Software"), to deal in the Software without restriction,
00238 including without limitation the rights to use, copy, modify, merge,
00239 publish, distribute, sublicense, and/or sell copies of the Software,
00240 and to permit persons to whom the Software is furnished to do so,
00241 subject to the following conditions:
00242 
00243 The above copyright notice and this permission notice shall be
00244 included in all copies or substantial portions of the Software.
00245 
00246 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00247 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00248 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00249 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
00250 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
00251 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00252 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00253 SOFTWARE.
00254 
00255  **/

ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:52 2011 by Doxygen 1.6.1