taskswitcher/contextengine/hgfswserver/engine/src/hgfswengine.cpp
changeset 4 4d54b72983ae
parent 3 fb3763350a08
child 5 c743ef5928ba
equal deleted inserted replaced
3:fb3763350a08 4:4d54b72983ae
     1 /*
       
     2  * ===========================================================================
       
     3  *  Name        : hgfswengine.cpp
       
     4  *  Part of     : Huriganes / Fast Swap Server
       
     5  *  Description : Task monitor engine
       
     6  *  Version     : %version: sa1spcx1#37 %
       
     7  *
       
     8  *  Copyright © 2008 Nokia Corporation.
       
     9  *  This material, including documentation and any related 
       
    10  *  computer programs, is protected by copyright controlled by 
       
    11  *  Nokia Corporation. All rights are reserved. Copying, 
       
    12  *  including reproducing, storing, adapting or translating, any 
       
    13  *  or all of this material requires the prior written consent of 
       
    14  *  Nokia Corporation. This material also contains confidential 
       
    15  *  information which may not be disclosed to others without the 
       
    16  *  prior written consent of Nokia Corporation.
       
    17  * ===========================================================================
       
    18  */
       
    19 
       
    20 #include "hgfswengine.h"
       
    21 #include "hgfsalwaysshownapplist.h"
       
    22 #include "hgfshiddenapplist.h"
       
    23 #include "hgfswidgetlist.h"
       
    24 #include "hgfswiconcache.h"
       
    25 #include "hgpreviewprovider.h"
       
    26 #include "hgfswclient.h"
       
    27 #include <apgtask.h>
       
    28 #include <AknDef.h>
       
    29 #include <apgwgnam.h>
       
    30 #include <mmf/common/mmfcontrollerpluginresolver.h> // for CleanupResetAndDestroyPushL
       
    31 #include <featmgr.h>
       
    32 #include <swi/swispubsubdefs.h>
       
    33 
       
    34 #include "enginelogging.h"
       
    35 
       
    36 // time to wait before refreshing content
       
    37 const TInt KContentRefreshDelay = 500000; // 0.5 sec
       
    38 
       
    39 // for screenshots, they are scaled down to (screensize/this_factor).
       
    40 const TInt KScreenSizeFactor = 2;
       
    41 
       
    42 // format to get a lowercase hex string prefixed with 0x
       
    43 _LIT( KHexFmt, "0x%x" );
       
    44 
       
    45 // --------------------------------------------------------------------------
       
    46 // CHgFswEngine::NewL
       
    47 // --------------------------------------------------------------------------
       
    48 //
       
    49 EXPORT_C CHgFswEngine* CHgFswEngine::NewL( MHgFswEngineObserver& aObserver )
       
    50     {
       
    51     CHgFswEngine* self = NewLC( aObserver );
       
    52     CleanupStack::Pop( self );
       
    53     return self;
       
    54     }
       
    55 
       
    56 // --------------------------------------------------------------------------
       
    57 // CHgFswEngine::NewLC
       
    58 // --------------------------------------------------------------------------
       
    59 //
       
    60 EXPORT_C CHgFswEngine* CHgFswEngine::NewLC( MHgFswEngineObserver& aObserver )
       
    61     {
       
    62     CHgFswEngine* self = new ( ELeave ) CHgFswEngine( aObserver );
       
    63     CleanupStack::PushL( self );
       
    64     self->ConstructL();
       
    65     return self;
       
    66     }
       
    67 
       
    68 // --------------------------------------------------------------------------
       
    69 // CHgFswEngine::CHgFswEngine
       
    70 // --------------------------------------------------------------------------
       
    71 //
       
    72 CHgFswEngine::CHgFswEngine( MHgFswEngineObserver& aObserver )
       
    73         : CActive( EPriorityStandard ), iObserver( aObserver )
       
    74     {
       
    75     CActiveScheduler::Add( this );
       
    76     }
       
    77 
       
    78 // --------------------------------------------------------------------------
       
    79 // CHgFswEngine::ConstructL
       
    80 // --------------------------------------------------------------------------
       
    81 //
       
    82 void CHgFswEngine::ConstructL()
       
    83     {
       
    84     iEnv = CEikonEnv::Static();
       
    85 
       
    86     User::LeaveIfError( iWsSession.Connect() );
       
    87     User::LeaveIfError( iAppArcSession.Connect() );
       
    88 
       
    89     iHiddenAppList = CHgFsHiddenAppList::NewL( *this );
       
    90     iAlwaysShownAppList = CHgFsAlwaysShownAppList::NewL();
       
    91 
       
    92     iWidgetsSupported = FeatureManager::FeatureSupported( KFeatureIdWebWidgets );
       
    93     if ( iWidgetsSupported )
       
    94         {
       
    95         iWidgetList = CHgFsWidgetList::NewL();
       
    96         }
       
    97 
       
    98     // create app icon retriever instance
       
    99     iAppIcons = CHgFswIconCache::NewL();
       
   100 
       
   101     // get an initial list of tasks
       
   102     iAppDataRefreshNeeded = ETrue;
       
   103     CollectTasksL();
       
   104 
       
   105     // listen for app screenshots
       
   106     iPreviewProvider = CHgFastSwapPreviewProvider::NewL( *this );
       
   107     SetPreviewParams();
       
   108     UpdatePreviewContent();
       
   109 
       
   110     iUpdateStarter = CPeriodic::NewL( CActive::EPriorityStandard );
       
   111     
       
   112     // start listening for swi ps property
       
   113     if ( iSwiProp.Attach( KUidSystemCategory,
       
   114             Swi::KUidSoftwareInstallKey ) == KErrNone )
       
   115         {
       
   116         iSwiProp.Subscribe( iStatus );
       
   117         SetActive();
       
   118         }
       
   119     }
       
   120 
       
   121 // --------------------------------------------------------------------------
       
   122 // CHgFswEngine::~CHgFswEngine
       
   123 // --------------------------------------------------------------------------
       
   124 //
       
   125 CHgFswEngine::~CHgFswEngine()
       
   126     {
       
   127     Cancel();
       
   128     iSwiProp.Close();
       
   129 
       
   130     delete iUpdateStarter;
       
   131     delete iPreviewProvider;
       
   132 
       
   133     // delete the bitmaps as the hash map cannot do that
       
   134     THashMapIter<TInt, CFbsBitmap*> iter( iScreenshots );
       
   135     while ( const TInt* key = iter.NextKey() )
       
   136         {
       
   137         CFbsBitmap** value = iter.CurrentValue();
       
   138         delete *value;
       
   139         }
       
   140     iScreenshots.Close();
       
   141     delete iAppIcons;
       
   142 
       
   143     iData.ResetAndDestroy();
       
   144     iWgIds.Close();
       
   145 
       
   146     delete iHiddenAppList;
       
   147     delete iAlwaysShownAppList;
       
   148     delete iWidgetList;
       
   149     iAppArcSession.Close();
       
   150     iWsSession.Close();
       
   151 
       
   152 //    delete iContextUtility;
       
   153     }
       
   154 
       
   155 // --------------------------------------------------------------------------
       
   156 // CHgFswEngine::FswDataL
       
   157 // --------------------------------------------------------------------------
       
   158 //
       
   159 EXPORT_C const RHgFswArray& CHgFswEngine::FswDataL()
       
   160     {
       
   161     HGLOG_CONTEXT( FswDataL, HGLOG_LOCAL );
       
   162     HGLOG1_IN( "dirty flag = %d", iTaskListDirty );
       
   163 
       
   164     // check the dirty flag and refresh if needed
       
   165     if ( iTaskListDirty )
       
   166         {
       
   167         CollectTasksL();
       
   168         // dirty flag is cleared in the above call
       
   169         }
       
   170 
       
   171     // Get app icon for entries without screenshot,
       
   172     // do this only here as the app icon is not needed in case a screenshot
       
   173     // is already available.
       
   174     for ( TInt i = 0, ie = iData.Count(); i != ie; ++i )
       
   175         {
       
   176         if ( !iData[i]->ScreenshotHandle() )
       
   177             {
       
   178             CFbsBitmap* bmp;
       
   179             CFbsBitmap* mask;
       
   180             TUid appUid = iData[i]->AppUid();
       
   181             // this will leave with -46 in case of widgets if we do not have AllFiles cap
       
   182             TRAPD( err, iAppIcons->GetIconL( appUid, bmp, mask ) );
       
   183             if ( err == KErrNone && bmp )
       
   184                 {
       
   185                 iData[i]->SetAppIconHandles( bmp->Handle(),
       
   186                     mask ? mask->Handle() : 0 );
       
   187                 }
       
   188             else
       
   189                 {
       
   190                 iAppIcons->DefaultIcon( bmp, mask );
       
   191                 iData[i]->SetAppIconHandles( bmp->Handle(),
       
   192                     mask ? mask->Handle() : 0 );
       
   193                 }
       
   194             }
       
   195         }
       
   196 
       
   197     HGLOG_OUT();
       
   198     return iData;
       
   199     }
       
   200 
       
   201 // --------------------------------------------------------------------------
       
   202 // CHgFswEngine::CloseAppL
       
   203 // --------------------------------------------------------------------------
       
   204 //
       
   205 EXPORT_C void CHgFswEngine::CloseAppL( TInt aWgId )
       
   206     {
       
   207     HGLOG_CONTEXT( CloseAppL, HGLOG_LOCAL );
       
   208     HGLOG1_IN( "aWgId = %d", aWgId );
       
   209 
       
   210     if ( iWidgetsSupported && aWgId < 0 && iWidgetAppUiWgId )
       
   211         {
       
   212         // for widgets clients see a wgid that is -1*(index+1)
       
   213         const RWidgetInfoArray& arr( iWidgetList->RunningWidgets() );
       
   214         // convert aWgId to an index in the list of running widgets
       
   215         TInt idx = -aWgId - 1;
       
   216         // if index is valid then handle the widget specially
       
   217         if ( idx >= 0 && idx < arr.Count() )
       
   218             {
       
   219             TWsEvent event;
       
   220             event.SetType( EEventUser );
       
   221             TUint8* eventData = event.EventData();
       
   222             // Fill bits 0-31 with widget application uid.
       
   223             reinterpret_cast<TUint32&>( *eventData ) = KWidgetAppUidValue;
       
   224             eventData += sizeof( TUint32 );
       
   225             // Fill bits 32-63 with uid of the widget that should be closed.
       
   226             reinterpret_cast<TUint32&>( *eventData ) = arr[idx]->iUid.iUid;
       
   227             // Send the event to Widget AppUi.
       
   228             iEnv->WsSession().SendEventToWindowGroup(
       
   229                 iWidgetAppUiWgId, event );
       
   230             // closing a widget may not cause a window group change so trigger
       
   231             // the update manually
       
   232             UpdateTaskList();
       
   233             HGLOG0_OUT( "widget processing finished" );
       
   234             return;
       
   235             }
       
   236         }
       
   237 
       
   238     TUid appUid = AppUidForWgIdL( aWgId );
       
   239     if ( !iAlwaysShownAppList->IsAlwaysShownApp( appUid ) )
       
   240         {
       
   241         // send window group event to kill the app
       
   242         TWsEvent event;
       
   243         event.SetTimeNow();
       
   244         event.SetType( KAknShutOrHideApp );
       
   245         iEnv->WsSession().SendEventToWindowGroup( aWgId, event );
       
   246         HGLOG0( HGLOG_INFO, "event sent to wg" );
       
   247         }
       
   248 
       
   249     HGLOG_OUT();
       
   250     }
       
   251 
       
   252 // --------------------------------------------------------------------------
       
   253 // CHgFswEngine::SwitchToAppL
       
   254 // --------------------------------------------------------------------------
       
   255 //
       
   256 EXPORT_C void CHgFswEngine::SwitchToAppL( TInt aWgId )
       
   257     {
       
   258     HGLOG_CONTEXT( SwitchToAppL, HGLOG_LOCAL );
       
   259     HGLOG1_IN( "aWgId = %d", aWgId );
       
   260 
       
   261     if ( iWidgetsSupported && aWgId < 0 )
       
   262         {
       
   263         // for widgets clients see a wgid that is -1*(index+1)
       
   264         const RWidgetInfoArray& arr( iWidgetList->RunningWidgets() );
       
   265         // convert aWgId to an index in the list of running widgets
       
   266         TInt idx = -aWgId - 1;
       
   267         // if index is valid then handle the widget specially
       
   268         if ( idx >= 0 && idx < arr.Count() )
       
   269             {
       
   270             SwitchToWidgetL( idx );
       
   271             HGLOG1_OUT( "switched to widget %d", idx );
       
   272             return;
       
   273             }
       
   274         }
       
   275 
       
   276     TApaTask task( iEnv->WsSession() );
       
   277     task.SetWgId( aWgId );
       
   278     task.BringToForeground();
       
   279 
       
   280     HGLOG_OUT();
       
   281     }
       
   282 
       
   283 // --------------------------------------------------------------------------
       
   284 // CHgFswEngine::SwitchToWidgetL
       
   285 // --------------------------------------------------------------------------
       
   286 //
       
   287 void CHgFswEngine::SwitchToWidgetL( TInt aWidgetIndex )
       
   288     {
       
   289     const RWidgetInfoArray& arr( iWidgetList->RunningWidgets() );
       
   290     RApaLsSession ls;
       
   291     User::LeaveIfError( ls.Connect() );
       
   292     CleanupClosePushL( ls );
       
   293     CApaCommandLine* cmdLine = CApaCommandLine::NewLC();
       
   294     cmdLine->SetCommandL( EApaCommandRun );
       
   295     TApaAppInfo info;
       
   296     iAppArcSession.GetAppInfo( info, arr[aWidgetIndex]->iUid ); // codescanner::accessArrayElementWithoutCheck2 (aWidgetIndex checked in SwitchToAppL())
       
   297     cmdLine->SetExecutableNameL( info.iFullName );
       
   298     ls.StartApp( *cmdLine );
       
   299     CleanupStack::PopAndDestroy( 2, &ls );
       
   300     }
       
   301 
       
   302 // --------------------------------------------------------------------------
       
   303 // CHgFswEngine::UpdateTaskList
       
   304 // Callback from appui
       
   305 // --------------------------------------------------------------------------
       
   306 //
       
   307 void CHgFswEngine::UpdateTaskList()
       
   308     {
       
   309     HGLOG_CONTEXT( UpdateTaskList, HGLOG_LOCAL );
       
   310     HGLOG_IN();
       
   311 
       
   312     // If no clients are subscribed for fsw content change notifications
       
   313     // then there is no need to waste time with rebuilding the task list,
       
   314     // just set the dirty flag.
       
   315     TInt listenerCount = iObserver.FswDataListenerCount();
       
   316     HGLOG1( HGLOG_INFO, "listener count = %d", listenerCount );
       
   317     if ( listenerCount > 0 )
       
   318         {
       
   319         // There can be many calls in a row, use a timer to prevent degrading
       
   320         // device performance.
       
   321         if ( !iUpdateStarter->IsActive() )
       
   322             {
       
   323             iUpdateStarter->Start( KContentRefreshDelay, 0,
       
   324                 TCallBack( UpdateStarterCallback, this ) );
       
   325             }
       
   326         }
       
   327     else
       
   328         {
       
   329         iTaskListDirty = ETrue;
       
   330         }
       
   331 
       
   332     // screenshot taking support - call Register and Unregister when needed
       
   333     UpdatePreviewContent();
       
   334 
       
   335     // get the foreground app uid and publish it to CFW if different than before
       
   336     TRAP_IGNORE( PublishFgAppUidL() );
       
   337     
       
   338     HGLOG_OUT();
       
   339     }
       
   340 
       
   341 // --------------------------------------------------------------------------
       
   342 // CHgFswEngine::ForegroundAppUidL
       
   343 // --------------------------------------------------------------------------
       
   344 //
       
   345 EXPORT_C TUid CHgFswEngine::ForegroundAppUidL( TInt aType )
       
   346     {
       
   347     // Do not use GetFocusWindowGroup or others.
       
   348     // We want to see only "real" application uids in FgApp,
       
   349     // i.e. stuff that would also be shown in the task swapper
       
   350     // area of Teleport.
       
   351 
       
   352     TUid result = KNullUid;
       
   353     RArray<RWsSession::TWindowGroupChainInfo> allWgIds;
       
   354     CleanupClosePushL( allWgIds );
       
   355     User::LeaveIfError( iWsSession.WindowGroupList( 0, &allWgIds ) );
       
   356     TInt count = allWgIds.Count();
       
   357     for ( TInt i = 0; i < count; ++i )
       
   358         {
       
   359         // Depending on aType we may not need to bother with iParentId here.
       
   360         // If aType == EUseEmbeddedUid => embedded apps are treated as others.
       
   361         // If aType == EUseStandaloneUid => embedded apps must be ignored.
       
   362         if ( allWgIds[i].iParentId > 0
       
   363                 && aType == CHgFswClient::EUseStandaloneUid )
       
   364             {
       
   365             continue;
       
   366             }
       
   367 
       
   368         CApaWindowGroupName* wgn = CApaWindowGroupName::NewLC(
       
   369             iWsSession, allWgIds[i].iId );
       
   370         TUid newUid = wgn->AppUid();
       
   371         TBool hidden = wgn->Hidden() || iHiddenAppList->IsHiddenL(
       
   372             newUid, iWsSession, allWgIds[i].iId );
       
   373         CleanupStack::PopAndDestroy( wgn );
       
   374 
       
   375         if ( !hidden && newUid.iUid )
       
   376             {
       
   377             result = newUid;
       
   378             break;
       
   379             }
       
   380         }
       
   381     CleanupStack::PopAndDestroy( &allWgIds );
       
   382     
       
   383     return result;
       
   384     }
       
   385 
       
   386 // --------------------------------------------------------------------------
       
   387 // CHgFswEngine::PublishFgAppUidL
       
   388 // --------------------------------------------------------------------------
       
   389 //
       
   390 void CHgFswEngine::PublishFgAppUidL()
       
   391     {
       
   392     HGLOG_CONTEXT( PublishFgAppUidL, HGLOG_LOCAL );
       
   393     HGLOG_IN();
       
   394 
       
   395     TUid newUid = ForegroundAppUidL( CHgFswClient::EUseEmbeddedUid );
       
   396     HGLOG2( HGLOG_INFO, "ws says: %x we have: %x", newUid.iUid, iFgAppUid.iUid );
       
   397     if ( iFgAppUid != newUid && newUid.iUid )
       
   398         {
       
   399         iFgAppUid = newUid;
       
   400         iFgAppUidStr.Format( KHexFmt, iFgAppUid.iUid );
       
   401         //PublishContextL( KHgCFTypeFgApp, iFgAppUidStr );
       
   402         }
       
   403 
       
   404     HGLOG_OUT();
       
   405     }
       
   406 
       
   407 // --------------------------------------------------------------------------
       
   408 // CHgFswEngine::PublishContextL
       
   409 // --------------------------------------------------------------------------
       
   410 //
       
   411 //void CHgFswEngine::PublishContextL( const TDesC& aType, const TDesC& aValue )
       
   412 //    {
       
   413 //    HGLOG_CONTEXT( PublishContextL, HGLOG_LOCAL );
       
   414 //    HGLOG2_IN( "%S: %S", &aType, &aValue );
       
   415 //    if ( !iContextUtility )
       
   416 //        {
       
   417 //        iContextUtility = CHgContextUtility::NewL();
       
   418 //        iContextUtility->AllowPublishFromBackground( ETrue );
       
   419 //        }
       
   420 //    iContextUtility->PublishContextL( aType, aValue );
       
   421 //    HGLOG_OUT();
       
   422 //    }
       
   423 
       
   424 // --------------------------------------------------------------------------
       
   425 // CHgFswEngine::UpdateStarterCallback
       
   426 // Callback for the timer
       
   427 // --------------------------------------------------------------------------
       
   428 //
       
   429 TInt CHgFswEngine::UpdateStarterCallback( TAny* aParam )
       
   430     {
       
   431     CHgFswEngine* self = static_cast<CHgFswEngine*>( aParam );
       
   432     self->iUpdateStarter->Cancel();
       
   433     // get list of tasks and notify observer if there is a change in the list
       
   434     TBool changed = EFalse;
       
   435     TRAPD( err, changed = self->CollectTasksL() );
       
   436     if ( err == KErrNone && changed )
       
   437         {
       
   438         self->iObserver.FswDataChanged();
       
   439         }
       
   440     return 0;
       
   441     }
       
   442 
       
   443 // --------------------------------------------------------------------------
       
   444 // CHgFswEngine::CollectTasksL
       
   445 // --------------------------------------------------------------------------
       
   446 //
       
   447 TBool CHgFswEngine::CollectTasksL()
       
   448     {
       
   449     HGLOG_CONTEXT( CollectTasksL, HGLOG_LOCAL );
       
   450     HGLOG_IN();
       
   451 
       
   452     // clear dirty flag
       
   453     iTaskListDirty = EFalse;
       
   454 
       
   455     TBool changed = EFalse;
       
   456     RHgFswArray newList;
       
   457     CleanupResetAndDestroyPushL( newList );
       
   458 
       
   459     // update app data if needed
       
   460     // (usually on startup and when new apps might have been installed)
       
   461     if ( iAppDataRefreshNeeded )
       
   462         {
       
   463         HGLOG0( HGLOG_INFO, "refreshing app data" );
       
   464         iAppArcSession.GetAllApps();
       
   465         iAlwaysShownAppList->InitializeAlwaysShownListL();
       
   466         iAppDataRefreshNeeded = EFalse;
       
   467         }
       
   468 
       
   469     // get all window groups
       
   470     RArray<RWsSession::TWindowGroupChainInfo> allWgIds;
       
   471     CleanupClosePushL( allWgIds );
       
   472     User::LeaveIfError( iWsSession.WindowGroupList( 0, &allWgIds ) );
       
   473     TInt count = allWgIds.Count();
       
   474 
       
   475     for ( TInt i = 0; i < count; ++i )
       
   476         {
       
   477         // ignore uninteresting entries (e.g. embedded apps)
       
   478         if ( allWgIds[i].iParentId > 0 )
       
   479             {
       
   480             continue;
       
   481             }
       
   482 
       
   483         // get window group name
       
   484         TInt wgId = allWgIds[i].iId;
       
   485         CApaWindowGroupName* windowName =
       
   486             CApaWindowGroupName::NewLC( iWsSession, wgId );
       
   487         TUid appUid = windowName->AppUid();
       
   488 
       
   489         // ignore entries with null uid
       
   490         if ( !appUid.iUid )
       
   491             {
       
   492             CleanupStack::PopAndDestroy( windowName );
       
   493             continue;
       
   494             }
       
   495 
       
   496         // will append the task to our own list only if it is not hidden
       
   497         TBool onHiddenList = iHiddenAppList->IsHiddenL(
       
   498             appUid, iWsSession, wgId );
       
   499 
       
   500         // if this is the widget app then save wgid for later use
       
   501         // and ignore it, but include running widgets instead
       
   502         if ( iWidgetsSupported && appUid.iUid == KWidgetAppUidValue )
       
   503             {
       
   504             iWidgetAppUiWgId = wgId;
       
   505             onHiddenList = ETrue;
       
   506             CheckWidgetsL( newList );
       
   507             }
       
   508 
       
   509         // get screen number (-1=console, 0=main screen, 1=cover ui)
       
   510         TInt appScreen = 0;
       
   511         TInt scrNumErr = iAppArcSession.GetDefaultScreenNumber( appScreen, appUid );
       
   512 
       
   513         // check if it is on always-shown list
       
   514         TBool mustShow = iAlwaysShownAppList->IsAlwaysShownApp( appUid );
       
   515 
       
   516 #ifdef _DEBUG
       
   517         const TDesC& captionDbg( windowName->Caption() );
       
   518         HGLOG4( HGLOG_INFO, "[%d] wgid=%d appuid=%x (%S)", i, wgId,
       
   519             appUid.iUid, &captionDbg );
       
   520         HGLOG4( HGLOG_INFO, "hidden=%d onhiddenlist=%d mustshow=%d scrno=%d",
       
   521             windowName->Hidden(), onHiddenList, mustShow, appScreen );
       
   522 #endif
       
   523 
       
   524         // add item to task list if it is always-shown OR it is not hidden
       
   525         // and it is not on cover ui
       
   526         if ( mustShow
       
   527                 || ( !onHiddenList
       
   528                     && !windowName->Hidden()
       
   529                     && ( appScreen == 0 || appScreen == -1 )
       
   530                     && scrNumErr == KErrNone ) )
       
   531             {
       
   532             if ( AddEntryL( wgId, appUid, windowName, newList, EFalse ) )
       
   533                 {
       
   534                 changed = ETrue;
       
   535                 }
       
   536             }
       
   537         CleanupStack::PopAndDestroy( windowName );
       
   538         }
       
   539     CleanupStack::PopAndDestroy( &allWgIds );    
       
   540 
       
   541     // if counts for old and new lists do not match then there is a change for sure,
       
   542     // probably an app has been closed
       
   543     if ( iData.Count() != newList.Count() )
       
   544         {
       
   545         changed = ETrue;
       
   546         }
       
   547 
       
   548     // move pointers from the temporary list into the real one
       
   549     iData.ResetAndDestroy();
       
   550     TInt newListCount = newList.Count();
       
   551     HGLOG1( HGLOG_INFO, "new list count = %d", newListCount );
       
   552     for ( TInt i = 0; i < newListCount; ++i )
       
   553         {
       
   554         HGLOG3( HGLOG_INFO, "[%d] %S wgid=%d",
       
   555             i, &newList[i]->AppName(), newList[i]->WgId() );
       
   556         iData.AppendL( newList[i] );
       
   557         newList[i] = 0;
       
   558         }
       
   559     CleanupStack::PopAndDestroy( &newList );
       
   560     
       
   561     HGLOG1_OUT( "change flag = %d", changed );
       
   562     return changed;
       
   563     }
       
   564 
       
   565 // --------------------------------------------------------------------------
       
   566 // CHgFswEngine::AddEntryL
       
   567 // --------------------------------------------------------------------------
       
   568 //
       
   569 TBool CHgFswEngine::AddEntryL( TInt aWgId, const TUid& aAppUid,
       
   570         CApaWindowGroupName* aWgName, RHgFswArray& aNewList,
       
   571         TBool aIsWidget )
       
   572     {
       
   573     TBool changed = EFalse;
       
   574     CHgFswEntry* entry = CHgFswEntry::NewLC();
       
   575     entry->SetWgId( aWgId );
       
   576     entry->SetAppUid( aAppUid );
       
   577     entry->SetWidget( aIsWidget );
       
   578 
       
   579     // check if present in old list and if yes then take some of the old data
       
   580     TBool found = CheckIfExistsL( *entry, aAppUid, changed, aNewList );
       
   581 
       
   582     // if not present previously then find out app name
       
   583     // and check if screenshot is already available
       
   584     if ( !found )
       
   585         {
       
   586         // when adding a new entry to the list it is changed for sure
       
   587         changed = ETrue;
       
   588         HBufC* name = FindAppNameLC( aWgName, aAppUid, aWgId );
       
   589         if ( name )
       
   590             {
       
   591             entry->SetAppNameL( *name );
       
   592             }
       
   593         CleanupStack::PopAndDestroy( name );
       
   594         TInt h = LookupScreenshotHandle( aWgId );
       
   595         if ( h )
       
   596             {
       
   597             entry->SetScreenshotHandle( h );
       
   598             }
       
   599         entry->SetAlwaysShown( iAlwaysShownAppList->IsAlwaysShownApp( aAppUid ) );
       
   600         if ( aWgName )
       
   601             {
       
   602             entry->SetSystemApp( aWgName->IsSystem() );
       
   603             }
       
   604         }
       
   605 
       
   606     // add to new list, ownership is transferred
       
   607     aNewList.AppendL( entry );
       
   608     CleanupStack::Pop( entry );
       
   609     return changed;
       
   610     }
       
   611 
       
   612 // --------------------------------------------------------------------------
       
   613 // CHgFswEngine::CheckIfExistsL
       
   614 // --------------------------------------------------------------------------
       
   615 //
       
   616 TBool CHgFswEngine::CheckIfExistsL( CHgFswEntry& aEntry,
       
   617         const TUid& aAppUid,
       
   618         TBool& aChanged,
       
   619         RHgFswArray& aNewList )
       
   620     {
       
   621     for ( TInt entryIdx = 0, oldCount = iData.Count();
       
   622             entryIdx < oldCount; ++entryIdx )
       
   623         {
       
   624         // Enough to check appuid, no need to bother with wgid as the
       
   625         // screenshot handle is up-to-date or will be updated later anyway.
       
   626         if ( iData[entryIdx]->AppUid() == aAppUid )
       
   627             {
       
   628             // if positions do not match then the list is different than before
       
   629             if ( entryIdx != aNewList.Count() )
       
   630                 {
       
   631                 aChanged = ETrue;
       
   632                 }
       
   633             CHgFswEntry* oldEntry = iData[entryIdx];
       
   634             aEntry.SetAppNameL( oldEntry->AppName() );
       
   635             aEntry.SetScreenshotHandle( oldEntry->ScreenshotHandle() );
       
   636             aEntry.SetAlwaysShown( oldEntry->AlwaysShown() );
       
   637             aEntry.SetSystemApp( oldEntry->SystemApp() );
       
   638             return ETrue;
       
   639             }
       
   640         }
       
   641     return EFalse;
       
   642     }
       
   643     
       
   644 // --------------------------------------------------------------------------
       
   645 // CHgFswEngine::CheckWidgetsL
       
   646 // --------------------------------------------------------------------------
       
   647 //
       
   648 void CHgFswEngine::CheckWidgetsL( RHgFswArray& aNewList )
       
   649     {
       
   650     if ( iWidgetsSupported )
       
   651         {
       
   652         iWidgetList->InitializeWidgetListL();
       
   653         const RWidgetInfoArray& arr( iWidgetList->RunningWidgets() );
       
   654         for ( TInt i = 0, ie = arr.Count(); i != ie; ++i )
       
   655             {
       
   656             // wgid will be a special negative value
       
   657             // windowgroupname is not needed here so pass NULL
       
   658             AddEntryL( -(i+1), arr[i]->iUid, 0, aNewList, ETrue );
       
   659             }
       
   660         }
       
   661     }
       
   662 
       
   663 // --------------------------------------------------------------------------
       
   664 // CHgFswEngine::HiddenAppListUpdated
       
   665 // Callback from the hidden app list watcher
       
   666 // --------------------------------------------------------------------------
       
   667 //
       
   668 void CHgFswEngine::HiddenAppListUpdated()
       
   669     {
       
   670     UpdateTaskList();
       
   671     }
       
   672 
       
   673 // --------------------------------------------------------------------------
       
   674 // CHgFswEngine::AppUidForWgIdL
       
   675 // --------------------------------------------------------------------------
       
   676 //
       
   677 TUid CHgFswEngine::AppUidForWgIdL( TInt aWgId )
       
   678     {
       
   679     CApaWindowGroupName* windowName =
       
   680         CApaWindowGroupName::NewLC( iWsSession, aWgId );
       
   681     TUid appUid = windowName->AppUid();
       
   682     CleanupStack::PopAndDestroy( windowName );
       
   683     return appUid;
       
   684     }
       
   685 
       
   686 // --------------------------------------------------------------------------
       
   687 // CHgFswEngine::FindParentWgId
       
   688 // --------------------------------------------------------------------------
       
   689 //
       
   690 TInt CHgFswEngine::FindParentWgId( TInt aWgId )
       
   691     {
       
   692     TInt parent( KErrNotFound );
       
   693     RArray<RWsSession::TWindowGroupChainInfo> allWgIds;
       
   694     // Ask for window group list from RWsSession
       
   695     TInt error = iWsSession.WindowGroupList( 0, &allWgIds );
       
   696     if ( !error )
       
   697         {
       
   698         TInt count( allWgIds.Count() );
       
   699         for ( TInt i( 0 ); i < count; i++ )
       
   700             {
       
   701             RWsSession::TWindowGroupChainInfo info = allWgIds[i];
       
   702             if ( info.iId == aWgId )
       
   703                 {
       
   704                 parent = info.iParentId;
       
   705                 break;
       
   706                 }
       
   707             }
       
   708         }
       
   709     allWgIds.Close();
       
   710     return parent;
       
   711     }
       
   712 
       
   713 // --------------------------------------------------------------------------
       
   714 // CHgFswEngine::FindAppNameLC
       
   715 // --------------------------------------------------------------------------
       
   716 //
       
   717 HBufC* CHgFswEngine::FindAppNameLC( CApaWindowGroupName* aWindowName,
       
   718                                   const TUid& aAppUid,
       
   719                                   TInt aWgId )
       
   720     {
       
   721     //Retrieve the app name
       
   722     TApaAppInfo info;
       
   723     iAppArcSession.GetAppInfo( info, aAppUid );
       
   724     TPtrC caption = info.iShortCaption;
       
   725 
       
   726     HBufC* tempName = 0;
       
   727     if ( !caption.Length() && aWindowName ) // if not set - use thread name instead
       
   728         {
       
   729         if ( aWindowName->Caption().Length() )
       
   730             {
       
   731             tempName = aWindowName->Caption().AllocL();
       
   732             //put on cleanupstack after the if
       
   733             }
       
   734         else
       
   735             {
       
   736             TThreadId threadId;
       
   737             TInt err = iWsSession.GetWindowGroupClientThreadId(
       
   738                     aWgId, threadId );
       
   739             if ( err == KErrNone )
       
   740                 {
       
   741                 RThread thread;
       
   742                 CleanupClosePushL( thread );
       
   743                 err = thread.Open ( threadId );
       
   744                 if ( err==KErrNone )
       
   745                     {
       
   746                     tempName = thread.Name().AllocL(); // codescanner::forgottoputptroncleanupstack
       
   747                     // tempName put on cleanupstack after the if
       
   748                     }
       
   749                 CleanupStack::PopAndDestroy( &thread );
       
   750                 }
       
   751             }
       
   752         }
       
   753     else
       
   754         {
       
   755         tempName = caption.AllocL();
       
   756         //put on cleanupstack after the if
       
   757         }
       
   758     CleanupStack::PushL( tempName );
       
   759     return tempName;
       
   760     }
       
   761 
       
   762 // --------------------------------------------------------------------------
       
   763 // CHgFswEngine::CopyBitmapL
       
   764 // --------------------------------------------------------------------------
       
   765 //
       
   766 CFbsBitmap* CHgFswEngine::CopyBitmapL( TInt aFbsHandle, TBool aKeepAspectRatio )
       
   767     {
       
   768     CFbsBitmap* ret = new (ELeave) CFbsBitmap;
       
   769     CleanupStack::PushL( ret );
       
   770     CFbsBitmap* bmp = new (ELeave) CFbsBitmap;
       
   771     CleanupStack::PushL( bmp );
       
   772     User::LeaveIfError( bmp->Duplicate( aFbsHandle ) );
       
   773 
       
   774     //Make bitmap width and height equal so that it will look better in FSW control.
       
   775     TSize size  = bmp->SizeInPixels();
       
   776 
       
   777     if ( !aKeepAspectRatio )
       
   778         {
       
   779         if ( size.iHeight > size.iWidth )
       
   780             {
       
   781             size.iHeight = size.iWidth;
       
   782             }
       
   783         else
       
   784             {
       
   785             size.iWidth = size.iHeight;
       
   786             }
       
   787         }
       
   788 
       
   789     // preserve size and mode
       
   790     User::LeaveIfError( ret->Create( size, EColor64K ) );
       
   791 
       
   792     CFbsBitmapDevice* doubleBufferDev = CFbsBitmapDevice::NewL( ret );
       
   793     CleanupStack::PushL( doubleBufferDev );
       
   794 
       
   795     CFbsBitGc* doubleBufferGc = 0;
       
   796     User::LeaveIfError( doubleBufferDev->CreateContext( doubleBufferGc ) );
       
   797     CleanupStack::PushL( doubleBufferGc );
       
   798 
       
   799     // preserve size
       
   800     doubleBufferGc->BitBlt( TPoint( 0, 0 ), bmp, TRect(size) );
       
   801 
       
   802     CleanupStack::PopAndDestroy( doubleBufferGc );
       
   803     CleanupStack::PopAndDestroy( doubleBufferDev );
       
   804     CleanupStack::PopAndDestroy( bmp );
       
   805     CleanupStack::Pop( ret );
       
   806 
       
   807     return ret;
       
   808     }
       
   809 
       
   810 // --------------------------------------------------------------------------
       
   811 // CHgFswEngine::UpdatePreviewContent
       
   812 // --------------------------------------------------------------------------
       
   813 //
       
   814 void CHgFswEngine::UpdatePreviewContent()
       
   815     {
       
   816     HGLOG_CONTEXT( UpdatePreviewContent, HGLOG_LOCAL );
       
   817     HGLOG_IN();
       
   818 
       
   819     RArray<RWsSession::TWindowGroupChainInfo> allWgIds;
       
   820     if ( iWsSession.WindowGroupList( 0, &allWgIds ) == KErrNone )
       
   821         {
       
   822         // check window groups that do not exist anymore
       
   823         for ( TInt i = 0, ie = iWgIds.Count(); i != ie; ++i )
       
   824             {
       
   825             TInt wgid = iWgIds[i];
       
   826             TBool present = EFalse;
       
   827             for ( TInt j = 0, je = allWgIds.Count(); j != je; ++j )
       
   828                 {
       
   829                 if ( allWgIds[j].iId == wgid )
       
   830                     {
       
   831                     present = ETrue;
       
   832                     break;
       
   833                     }
       
   834                 }
       
   835             if ( !present )
       
   836                 {
       
   837                 HGLOG1( HGLOG_INFO, "unregister: %d", wgid );
       
   838                 iPreviewProvider->Unregister( wgid );
       
   839                 }
       
   840             }
       
   841         // check topmost window group
       
   842         if ( allWgIds.Count() )
       
   843             {
       
   844             if ( !iWgIds.Count() || allWgIds[0].iId != iWgIds[0] )
       
   845                 {
       
   846                 TInt wgid = allWgIds[0].iId;
       
   847                 HGLOG1( HGLOG_INFO, "registering %d", wgid );
       
   848                 iPreviewProvider->Register( wgid );
       
   849                 }
       
   850             }
       
   851         // store the new list
       
   852         iWgIds.Reset();
       
   853         for ( TInt i = 0, ie = allWgIds.Count(); i != ie; ++i )
       
   854             {
       
   855             iWgIds.Append( allWgIds[i].iId );
       
   856             }
       
   857         }
       
   858     allWgIds.Close();
       
   859 
       
   860     HGLOG_OUT();
       
   861     }
       
   862 
       
   863 // --------------------------------------------------------------------------
       
   864 // CHgFswEngine::HandleFswPpApplicationChange
       
   865 // Callback from CHgFastSwapPreviewProvider
       
   866 // Note: aWgId is for the window group for which the screenshot is taken,
       
   867 // it may not be the same as the application's wgid (in case of embedded apps)
       
   868 // --------------------------------------------------------------------------
       
   869 //
       
   870 void CHgFswEngine::HandleFswPpApplicationChange( TInt aWgId, TInt aFbsHandle )
       
   871     {
       
   872     HGLOG_CONTEXT( HandleFswPpApplicationChange, HGLOG_LOCAL );
       
   873     HGLOG2_IN( "aWgId = %d aFbsHandle = %d", aWgId, aFbsHandle );
       
   874 
       
   875     CFbsBitmap* bmp = 0;
       
   876     TRAPD( err, bmp = CopyBitmapL( aFbsHandle, EFalse ) );
       
   877     iPreviewProvider->AckPreview(aFbsHandle);
       
   878     if ( err == KErrNone )
       
   879         {
       
   880         CFbsBitmap** oldbmp = iScreenshots.Find( aWgId );
       
   881         if ( oldbmp )
       
   882             {
       
   883             delete *oldbmp;
       
   884             }
       
   885         if ( iScreenshots.Insert( aWgId, bmp ) != KErrNone )
       
   886             {
       
   887             delete bmp;
       
   888             iScreenshots.Remove( aWgId );
       
   889             }
       
   890         else
       
   891             {
       
   892             AssignScreenshotHandle( aWgId, bmp->Handle() );
       
   893             }
       
   894         }
       
   895 
       
   896     HGLOG_OUT();
       
   897     }
       
   898 
       
   899 // --------------------------------------------------------------------------
       
   900 // CHgFswEngine::HandleFswPpApplicationUnregistered
       
   901 // Callback from CHgFastSwapPreviewProvider
       
   902 // --------------------------------------------------------------------------
       
   903 //
       
   904 void CHgFswEngine::HandleFswPpApplicationUnregistered( TInt aWgId )
       
   905     {
       
   906     HGLOG_CONTEXT( HandleFswPpApplicationUnregistered, HGLOG_LOCAL );
       
   907     HGLOG1_IN( "aWgId = %d", aWgId );
       
   908 
       
   909     CFbsBitmap** bmp = iScreenshots.Find( aWgId );
       
   910     if ( bmp )
       
   911         {
       
   912         delete *bmp;
       
   913         iScreenshots.Remove( aWgId );
       
   914         AssignScreenshotHandle( aWgId, 0 );
       
   915         }
       
   916 
       
   917     HGLOG_OUT();
       
   918     }
       
   919 
       
   920 // --------------------------------------------------------------------------
       
   921 // CHgFswEngine::AssignScreenshotHandle
       
   922 // Called when a screenshot arrives to check if there is a corresponding
       
   923 // application in the task list.
       
   924 // --------------------------------------------------------------------------
       
   925 //
       
   926 void CHgFswEngine::AssignScreenshotHandle( TInt aWgIdForScreenshot,
       
   927         TInt aBitmapHandle )
       
   928     {
       
   929     TBool changed = EFalse;
       
   930     TInt parentWgId = FindParentWgId( aWgIdForScreenshot );
       
   931     // now parentWgId is a valid wgid or KErrNotFound (-1)
       
   932     for ( TInt i = 0, ie = iData.Count(); i != ie; ++i )
       
   933         {
       
   934         if ( iData[i]->Widget() )
       
   935             {
       
   936             // Do not do anything for now => no screenshot for widgets.
       
   937             continue;
       
   938             }
       
   939         TInt appWgId = iData[i]->WgId();
       
   940         if ( appWgId == aWgIdForScreenshot || appWgId == parentWgId )
       
   941             {
       
   942             iData[i]->SetScreenshotHandle( aBitmapHandle );
       
   943             changed = ETrue;
       
   944             break;
       
   945             }
       
   946         }
       
   947     if ( changed )
       
   948         {
       
   949         iObserver.FswDataChanged();
       
   950         }
       
   951     }
       
   952 
       
   953 // --------------------------------------------------------------------------
       
   954 // CHgFswEngine::LookupScreenshotHandle
       
   955 // Called to check if there is a screenshot already stored for the given
       
   956 // app. (or a screenshot with a wgid for which aWgIdForApp is the parent)
       
   957 // --------------------------------------------------------------------------
       
   958 //
       
   959 TInt CHgFswEngine::LookupScreenshotHandle( TInt aWgIdForApp )
       
   960     {
       
   961     CFbsBitmap** bmp = iScreenshots.Find( aWgIdForApp );
       
   962     if ( bmp )
       
   963         {
       
   964         // there is a screenshot stored for this wgid
       
   965         return (*bmp)->Handle();
       
   966         }
       
   967     else if ( aWgIdForApp > 0 )
       
   968         {
       
   969         // must check if there is a screenshot for which aWgIdForApp is the parent
       
   970         THashMapIter<TInt, CFbsBitmap*> iter( iScreenshots );
       
   971         while ( const TInt* wgid = iter.NextKey() )
       
   972             {
       
   973             if ( FindParentWgId( *wgid ) == aWgIdForApp )
       
   974                 {
       
   975                 CFbsBitmap** bmp = iter.CurrentValue();
       
   976                 return (*bmp)->Handle();
       
   977                 }
       
   978             }
       
   979         }
       
   980     else if ( aWgIdForApp < 0 )
       
   981         {
       
   982         // Must be a widget, wgid is useless in this case.
       
   983         // Do not do anything for now => no screenshot for widgets.
       
   984         }
       
   985     return 0;
       
   986     }
       
   987 
       
   988 // --------------------------------------------------------------------------
       
   989 // CHgFswEngine::RunL
       
   990 // --------------------------------------------------------------------------
       
   991 //
       
   992 void CHgFswEngine::RunL()
       
   993     {
       
   994     if ( iStatus != KErrCancel ) // when cancelling the subscribe it completes with KErrCancel
       
   995         {
       
   996         TInt value = 0;
       
   997         if ( iSwiProp.Get( value ) == KErrNone )
       
   998             {
       
   999             TInt operationStatus( value & Swi::KSwisOperationStatusMask );
       
  1000             // When an (un)installation has finished change the flag to
       
  1001             // refresh the app list during the next task list update.
       
  1002             if ( operationStatus == Swi::ESwisStatusSuccess )
       
  1003                 {
       
  1004                 iAppDataRefreshNeeded = ETrue;
       
  1005                 }
       
  1006             }
       
  1007         iSwiProp.Subscribe( iStatus );
       
  1008         SetActive();
       
  1009         }
       
  1010     }
       
  1011 
       
  1012 // --------------------------------------------------------------------------
       
  1013 // CHgFswEngine::DoCancel
       
  1014 // --------------------------------------------------------------------------
       
  1015 //
       
  1016 void CHgFswEngine::DoCancel()
       
  1017     {
       
  1018     iSwiProp.Cancel();
       
  1019     }
       
  1020 
       
  1021 // --------------------------------------------------------------------------
       
  1022 // CHgFswEngine::RunError
       
  1023 // --------------------------------------------------------------------------
       
  1024 //
       
  1025 TInt CHgFswEngine::RunError( TInt /*aError*/ )
       
  1026     {
       
  1027     return KErrNone;
       
  1028     }
       
  1029 
       
  1030 // --------------------------------------------------------------------------
       
  1031 // CHgFswEngine::HandleResourceChange
       
  1032 // callback from appui's HandleResourceChangeL
       
  1033 // --------------------------------------------------------------------------
       
  1034 //
       
  1035 void CHgFswEngine::HandleResourceChange( TInt aType )
       
  1036     {
       
  1037     HGLOG_CONTEXT( HandleResourceChange, HGLOG_LOCAL );
       
  1038     HGLOG_IN();
       
  1039 
       
  1040     if ( iPreviewProvider && aType == KEikDynamicLayoutVariantSwitch )
       
  1041         {
       
  1042         SetPreviewParams();
       
  1043         }
       
  1044 
       
  1045     HGLOG_OUT();
       
  1046     }
       
  1047 
       
  1048 // --------------------------------------------------------------------------
       
  1049 // CHgFswEngine::SetPreviewParams
       
  1050 // --------------------------------------------------------------------------
       
  1051 //
       
  1052 void CHgFswEngine::SetPreviewParams()
       
  1053     {
       
  1054     TSize screenSize = iEnv->ScreenDevice()->SizeInPixels();
       
  1055     iPreviewProvider->SetPreviewParam(
       
  1056         TSize( screenSize.iWidth / KScreenSizeFactor,
       
  1057             screenSize.iHeight / KScreenSizeFactor ),
       
  1058         EColor64K ); // displaymode is ignored
       
  1059     }
       
  1060 
       
  1061     
       
  1062 // end of file