fotaapplication/fotaserver/src/fotaupdate.cpp
branchRCL_3
changeset 25 b183ec05bd8c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fotaapplication/fotaserver/src/fotaupdate.cpp	Tue Aug 31 16:04:06 2010 +0300
@@ -0,0 +1,722 @@
+/*
+ * Copyright (c) 2005-2006 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:   starts update sequence
+ *
+ */
+
+// INCLUDE FILES
+#include <StringLoader.h>
+#include <centralrepository.h>
+#include <AknUtils.h>
+#include <AknBidiTextUtils.h> 
+#include <biditext.h>
+#include <gdi.h>
+#include <fotaengine.h>
+#include <apgtask.h>
+#include <aknradiobuttonsettingpage.h> 
+#include <akntitle.h>
+#include <schtime.h>
+#include <csch_cli.h>
+#include <fotaengine.h>
+#include <XQConversions>
+#include "fotaupdate.h"
+#include "fmsclient.h"
+#include "FotasrvSession.h"
+#include "fotaserverPrivateCRKeys.h"
+#include "fotaserverPrivatePSKeys.h"
+#include "fotanotifiers.h"
+
+#include <usbman.h>
+#include <usbstates.h>
+// ============================= MEMBER FUNCTIONS ============================
+
+
+// ---------------------------------------------------------------------------
+// CFotaUpdate::CFotaUpdate()
+// ---------------------------------------------------------------------------
+//
+CFotaUpdate::CFotaUpdate() :
+    CActive(EPriorityNormal)
+    {
+    CActiveScheduler::Add(this);
+    }
+
+// ---------------------------------------------------------------------------
+// CFotaUpdate::~CFotaUpdate()
+// ---------------------------------------------------------------------------
+//
+CFotaUpdate::~CFotaUpdate()
+    {
+    FLOG(_L("CFotaUpdate::~CFotaUpdate >>"));
+    iFotaServer = NULL;
+
+    CancelMonitor();
+
+    if (iProperty.Handle())
+        iProperty.Close();
+
+    FLOG(_L("CFotaUpdate::~CFotaUpdate <<"));
+    }
+
+// ---------------------------------------------------------------------------
+// CFotaUpdate::NewL 
+// ---------------------------------------------------------------------------
+//
+CFotaUpdate* CFotaUpdate::NewL(CFotaServer* aServer)
+    {
+    CFotaUpdate* ao = new (ELeave) CFotaUpdate();
+    ao->iFotaServer = aServer;
+    return ao;
+    }
+
+// ---------------------------------------------------------------------------
+// CFotaUpdate::CheckUpdateResults
+// Checks if there is update result file available (meaning that update just
+// took place)
+// ---------------------------------------------------------------------------
+//
+TBool CFotaUpdate::CheckUpdateResults(RFs& aRfs)
+    {
+    RFile f;
+    TInt err;
+    err = f.Open(aRfs, KUpdateResultFile, EFileShareAny);
+    f.Close();
+    if (err != KErrNone)
+        {
+        return EFalse;
+        }
+    FLOG(_L(" CFotaUpdate::CheckUpdateResults  update result file Found! "));
+    return ETrue;
+    }
+
+// ---------------------------------------------------------------------------
+// CFotaUpdate::ExecuteUpdateResultFileL
+// Read result code from update result file and update state accordingly. 
+// Show notifier "Update succesful". Do some cleanup.
+// ---------------------------------------------------------------------------
+//
+void CFotaUpdate::ExecuteUpdateResultFileL()
+    {
+    FLOG(_L("CFotaUpdate::ExecuteUpdateResultFileL >>"));
+
+    TInt err;
+    RFileReadStream rstr;
+    TInt result;
+    TInt msglen;
+    HBufC8* message = NULL;
+    HBufC16* message16 = NULL;
+    TBool deleteData(EFalse);
+
+    // Open update result file
+    FLOG(_L("opening rstr 1/2  "));
+    err = rstr.Open(iFotaServer->iFs, KUpdateResultFile, EFileRead
+            | EFileStream);
+    FLOG(_L("opened  rstr 2/2  "));
+    if (err)
+    	{
+        FLOG(_L("   update result file open err %d"), err);
+      }
+    User::LeaveIfError(err);
+    FLOG(_L("       0.1"));
+    CleanupClosePushL(rstr);
+    FLOG(_L("       0.2"));
+
+    // Read resultcode 
+    result = rstr.ReadUint32L();
+    msglen = rstr.ReadUint32L();
+    if (msglen != 0)
+        {
+        message = HBufC8::NewLC(msglen + 1);
+        TPtr8 ptrdesc = message->Des();
+        TRAPD ( err2, rstr.ReadL(ptrdesc) );
+        if (err2 != KErrNone && err2 != KErrEof)
+            {
+            FLOG(_L("  file read err %d"), err2);
+            User::Leave(err2);
+            }
+
+        message16 = HBufC16::NewLC(message->Des().Length());
+        message16->Des().Copy(*message);
+        FLOG(_L("   1 update result: %d"), result);
+        FLOG(_L("   2 dbg msg: %S"), message16);
+        CleanupStack::PopAndDestroy(message16);
+        CleanupStack::PopAndDestroy(message);
+        }
+
+    FLOG(_L("       0.6 "));
+    CleanupStack::PopAndDestroy(&rstr);
+
+    // Map resultcode to FUMO result code
+    RFotaEngineSession::TState fstate = RFotaEngineSession::EUpdateFailed;
+    RFotaEngineSession::TResult fresult =
+            RFotaEngineSession::EResUpdateFailed;
+
+    FLOG(_L("   3"));
+    switch (result)
+        {
+        case UPD_OK:
+            {
+            fstate = RFotaEngineSession::EUpdateSuccessfulNoData;
+            fresult = RFotaEngineSession::EResSuccessful;
+            deleteData = ETrue;
+            ShowDialogL(EFwUpdSuccess);
+            }
+            break;
+        case UPD_INSTALL_REQUEST_IS_INVALID:
+            {
+            fstate = RFotaEngineSession::EUpdateFailedNoData;
+            fresult = RFotaEngineSession::EResUpdateFailed;
+            deleteData = ETrue;
+            ShowDialogL(EFwUpdNotCompatible);
+            }
+            break;
+        case UPD_UPDATE_PACKAGE_IS_ABSENT:
+            {
+            fstate = RFotaEngineSession::EUpdateFailedNoData;
+            fresult = RFotaEngineSession::EResUpdateFailed;
+            ShowDialogL(EFwUpdNotCompatible);
+            }
+            break;
+        case UPD_UPDATE_PACKAGE_IS_CORRUPTED:
+            {
+            fstate = RFotaEngineSession::EUpdateFailedNoData;
+            fresult = RFotaEngineSession::EResCorruptedFWUPD;
+            deleteData = ETrue;
+            ShowDialogL(EFwUpdNotCompatible);
+            }
+            break;
+        case UPD_UPDATE_PACKAGE_CONTENTS_IS_INVALID:
+            {
+            fstate = RFotaEngineSession::EUpdateFailedNoData;
+            fresult = RFotaEngineSession::EResCorruptedFWUPD;
+            deleteData = ETrue;
+            ShowDialogL(EFwUpdNotCompatible);
+            }
+            break;
+        case UPD_UPDATE_PACKAGE_IS_NOT_COMPATIBLE_WITH_CURRENT_MOBILE_DEVICE:
+            {
+            fstate = RFotaEngineSession::EUpdateFailedNoData;
+            fresult = RFotaEngineSession::EResPackageMismatch;
+            deleteData = ETrue;
+            ShowDialogL(EFwUpdNotCompatible);
+            }
+            break;
+        case UPD_FATAL_ERROR:
+            {
+            fstate = RFotaEngineSession::EUpdateFailedNoData;
+            fresult = RFotaEngineSession::EResUpdateFailed;
+            deleteData = ETrue;
+            ShowDialogL(EFwUpdNotCompatible);
+            }
+            break;
+
+        default:
+            {
+            FLOG(_L("   3.1 invalid result: %d"), result);
+            fstate = RFotaEngineSession::EUpdateFailedNoData;
+            fresult = RFotaEngineSession::EResUpdateFailed;
+            deleteData = ETrue;
+            ShowDialogL(EFwUpdNotCompatible);
+            }
+            break;
+        }
+
+    // Find the state 60 (update  progressing) -> 100 (etc)
+    RArray<TInt> states;
+    TPackageState state;
+    CleanupClosePushL(states);
+    iFotaServer->iDatabase->OpenDBL();
+    iFotaServer->iDatabase->GetAllL(states);
+
+    FLOG(_L("   4.1 found %d states "), states.Count());
+    for (TInt i = 0; i < states.Count(); ++i)
+        {
+        TPackageState tmp;
+        TBuf8<KMaxFileName> tmpurl;
+        tmp = iFotaServer->iDatabase->GetStateL(states[i], tmpurl);
+        FLOG(_L("   5 got state "));
+        if (tmp.iState == RFotaEngineSession::EUpdateProgressing)
+            {
+            state = tmp;
+            state.iState = fstate;
+            state.iResult = fresult;
+            FLOG(_L("   6 Updating state id %d  to %d ,result %d  "),
+                    state.iPkgId, state.iState, state.iResult);
+            iFotaServer->iDatabase->SetStateL(state, KNullDesC8, EFDBState
+                    | EFDBResult);
+            }
+        }
+    iFotaServer->iDatabase->CloseAndCommitDB();
+    CleanupStack::PopAndDestroy(&states);
+
+    // Delete request file
+    err = BaflUtils::DeleteFile(iFotaServer->iFs, KUpdateRequestFile);
+    if (err != KErrNone && err != KErrNotFound)
+        {
+        FLOG(_L("   6.1  req file deleted, err %d"), err);
+        User::Leave(err);
+        }
+
+    // Write timestamp (shown to user in device management ui)
+    if (fresult == RFotaEngineSession::EResSuccessful)
+        {
+        RFileWriteStream wstr;
+        TTime time;
+        User::LeaveIfError(wstr.Replace(iFotaServer->iFs,
+                KUpdateTimeStampFileName, EFileWrite));
+        CleanupClosePushL(wstr);
+        time.HomeTime();
+        TInt year = time.DateTime().Year();
+        TInt month = time.DateTime().Month();
+        TInt day = time.DateTime().Day();
+        TInt hour = time.DateTime().Hour();
+        TInt minute = time.DateTime().Minute();
+        wstr.WriteInt32L(year);
+        wstr.WriteInt32L(month);
+        wstr.WriteInt32L(day);
+        wstr.WriteInt32L(hour);
+        wstr.WriteInt32L(minute);
+        CleanupStack::PopAndDestroy(1); // wstr
+        }
+    // Delete package content
+    if (deleteData && state.iPkgId > KErrNotFound)
+        {
+        iFotaServer->DeletePackageL(state.iPkgId);
+        DeleteUpdateResultFileL();
+        }
+
+    // Report state back to syncml server
+    if (state.iPkgId >= 0)
+        {
+        FLOG(_L("   6.1 creating device mgmt session for profile %d"),
+                state.iProfileId);
+        iFotaServer->ReportFwUpdateStatusL(state);
+        }
+    else
+        {
+        FLOG(_L(" No state found in 'update progress' mode! cannot report status to DM server "));
+        }
+
+    FLOG(_L("CFotaUpdate::ExecuteUpdateResultFileL <<"));
+    }
+
+// ---------------------------------------------------------------------------
+// CFotaUpdate::DeleteUpdateResultsL
+// ---------------------------------------------------------------------------
+//
+void CFotaUpdate::DeleteUpdateResultFileL()
+    {
+    FLOG(_L("CFotaUpdate::DeleteUpdateResultsL >>"));
+    // Delete result file
+    RFs fs;
+    __LEAVE_IF_ERROR(fs.Connect());
+    BaflUtils::DeleteFile(fs, KUpdateResultFile);
+    BaflUtils::DeleteFile(fs, KUpdateRequestFile);
+    BaflUtils::DeleteFile(fs, KUpdateBitmap);
+    BaflUtils::DeleteFile(fs, KRestartingBitmap);
+    fs.Close();
+    FLOG(_L("CFotaUpdate::DeleteUpdateResultsL <<"));
+    }
+
+// ---------------------------------------------------------------------------
+// CFotaUpdate::UpdateL
+// Updates the fw: Creates input files for update agent and boots device to 
+// update mode.
+// ---------------------------------------------------------------------------
+void CFotaUpdate::UpdateL()
+    {
+    FLOG(_L("CFotaUpdate::UpdateL() >>"));
+    // Set state ........................................
+    iFotaServer->iPackageState.iState
+            = RFotaEngineSession::EUpdateProgressing;
+    iFotaServer->iDatabase->OpenDBL();
+    iFotaServer->iDatabase->SetStateL(iFotaServer->iPackageState, KNullDesC8,
+            EFDBState);
+    iFotaServer->iDatabase->CloseAndCommitDB();
+
+    // Write update request for update agent..............
+    FLOG(_L("CFotaUpdate::UpdateL  1 writing update.req "));
+    TBuf16<KMaxFileName> dp2filepath;
+    HBufC16* dp2;
+    RFileWriteStream wstr;
+    CleanupClosePushL(wstr);
+    FLOG(_L("CFotaUpdate::UpdateL  2 getting pkg location"));
+    iFotaServer->DownloaderL()->GetUpdatePackageLocation(dp2filepath);
+
+    FLOG(_L("CFotaUpdate::UpdateL  3 craeting update.req"));
+    User::LeaveIfError(wstr.Replace(iFotaServer->iFs, KUpdateRequestFile,
+            EFileWrite));
+    wstr.WriteInt16L(1); // version number is  1
+    wstr.WriteInt32L(1); // count   of cmds is 1
+    wstr.WriteInt16L(0); // requestid is 0
+
+    dp2 = HBufC16::NewLC(dp2filepath.Length());
+    dp2->Des().Copy(dp2filepath);
+    wstr.WriteInt32L(dp2->Des().Length() + 1); // length of filename + null
+    wstr.WriteL(dp2->Des());
+    wstr.WriteInt16L(0); // null character
+    CleanupStack::PopAndDestroy(dp2);
+    CleanupStack::PopAndDestroy(&wstr); // wstr
+
+    FLOG(_L("CFotaUpdate::UpdateL  4 craeting update.bmp"));
+
+
+    // Write update graphic for update agent ...............
+    HBufC* updatetxt;
+    HBufC* restarttxt;
+    QString installstr = hbTrId("txt_device_update_info_installing");
+    QString rebootstr = hbTrId("txt_device_update_info_rebooting");
+    updatetxt = XQConversions::qStringToS60Desc(installstr);
+    restarttxt = XQConversions::qStringToS60Desc(rebootstr);
+    
+    WriteUpdateBitmapL( updatetxt->Des(), KUpdateBitmap );
+    WriteUpdateBitmapL( restarttxt->Des(), KRestartingBitmap );
+    delete updatetxt;
+    delete restarttxt;
+    
+    // Simulate update agent by writing result file.
+    CRepository* centrep(NULL);
+    TInt err = KErrNone;
+    TRAP(err, centrep = CRepository::NewL( KCRUidFotaServer ) );
+    TInt simulate(KErrNotFound);
+    if (centrep)
+        {
+        err = centrep->Get(KSimulateUpdateAgent, simulate);
+        }
+    delete centrep;
+    if (simulate > 0)
+        {
+        FLOG(_L("CFotaUpdate::UpdateL  5  - writing update.resp"));
+        RFileWriteStream respstr;
+        CleanupClosePushL(respstr);
+        User::LeaveIfError(respstr.Replace(iFotaServer->iFs,
+                KUpdateResultFile, EFileWrite));
+
+        respstr.WriteUint32L(UPD_OK);
+        respstr.WriteUint32L(15);
+        respstr.WriteL(_L("UPDATE DONE!"));
+        CleanupStack::PopAndDestroy(&respstr);
+        }
+
+    iFotaServer->SetStartupReason(EFotaDefault);
+    
+    RStarterSession starter;
+    FLOG(_L("           starter->Connect"));
+    User::LeaveIfError(starter.Connect());
+    starter.Reset(RStarterSession::EFirmwareUpdate);
+    starter.Close();
+    FLOG(_L("CFotaUpdate::UpdateL() <<"));
+    }
+
+// ---------------------------------------------------------------------------
+// CFotaUpdate::CheckBatteryL()
+// Cheks if there's enough battery power to update
+// ---------------------------------------------------------------------------
+//
+TBool CFotaUpdate::CheckBatteryL()
+    {
+    FLOG(_L("CFotaUpdate::CheckBatteryL >>"));
+
+    TInt chargingstatus(EChargingStatusError);
+    TInt batterylevel(EBatteryLevelUnknown);
+    TBool enoughPower(EFalse);
+
+    // Read battery level
+
+    RProperty pw;
+    User::LeaveIfError(pw.Attach(KPSUidHWRMPowerState, KHWRMBatteryLevel));
+    User::LeaveIfError(pw.Get(batterylevel));
+
+    if (batterylevel >= BatteryLevelAccepted)
+        {
+        FLOG(_L("Battery charge is above acceptable level!"));
+        enoughPower = ETrue;
+        }
+    else
+        {
+
+        //Read charger status
+        User::LeaveIfError(pw.Attach(KPSUidHWRMPowerState,
+                KHWRMChargingStatus));
+        User::LeaveIfError(pw.Get(chargingstatus));
+        pw.Close();
+
+        // But charger is connected, power sufficient
+        if (chargingstatus == EChargingStatusCharging || chargingstatus
+                == EChargingStatusAlmostComplete || chargingstatus
+                == EChargingStatusChargingComplete || chargingstatus
+                == EChargingStatusChargingContinued)
+            {
+            FLOG(
+                    _L("Battery charge is below acceptable level, but charger is connected!"));
+            enoughPower = ETrue;
+            }
+        }
+
+    FLOG(_L("CFotaUpdate::CheckBattery, current charge = %d, ret = %d <<"),
+            batterylevel, enoughPower);
+    return enoughPower;
+    }
+
+void CFotaUpdate::MonitorBatteryChargeLevel()
+    {
+    FLOG(_L("CFotaUpdate::MonitorBatteryChargeLevel >>"));
+
+    CancelMonitor();
+
+    iProperty.Attach(KPSUidHWRMPowerState, KHWRMBatteryLevel);
+    TInt value = 0;
+
+    iProperty.Get(KPSUidHWRMPowerState, KHWRMBatteryLevel, value);
+
+    FLOG(_L("Battery level at this time is %d, err = %d"), value);
+    iStatus = KRequestPending;
+    iProperty.Subscribe(iStatus);
+
+    iMonitorType = BatteryLevel;
+    SetActive();
+
+    FLOG(_L("CFotaUpdate::MonitorBatteryChargeLevel <<"));
+    }
+
+void CFotaUpdate::MonitorBatteryChargingStatus()
+    {
+    FLOG(_L("CFotaUpdate::MonitorBatteryChargingStatus >>"));
+
+    CancelMonitor();
+
+    iProperty.Attach(KPSUidHWRMPowerState, KHWRMChargingStatus);
+    TInt value = 0;
+
+    iProperty.Get(KPSUidHWRMPowerState, KHWRMChargingStatus, value);
+
+    FLOG(_L("Charging status at this time is %d, err = %d"), value);
+    iStatus = KRequestPending;
+    iProperty.Subscribe(iStatus);
+
+    iMonitorType = ChargingStatus;
+    SetActive();
+
+    FLOG(_L("CFotaUpdate::MonitorBatteryChargingStatus <<"));
+    }
+
+void CFotaUpdate::CancelMonitor()
+    {
+    FLOG(_L("CFotaUpdate::CancelMonitor >>"));
+    if (IsActive())
+        {
+        FLOG(_L("Cancelling...."));
+        Cancel();
+        }
+    FLOG(_L("CFotaUpdate::CancelMonitor <<"));
+    }
+
+TBool CFotaUpdate::IsUSBConnected()
+    {
+    FLOG(_L("CFotaUpdate::IsUSBConnected >>"));
+    
+    TBool ret (EFalse);
+    TUsbDeviceState state(EUsbDeviceStateUndefined);
+    RUsb usbman;
+    TInt err = usbman.Connect();
+    if (err == KErrNone)
+        {
+        usbman.GetDeviceState(state);
+        usbman.Close();
+        }
+    if (state != EUsbDeviceStateUndefined)
+    	{
+        ret = ETrue;
+      }
+    
+    FLOG(_L("CFotaUpdate::IsUSBConnected, value = %d, ret = %d <<"), state, ret);
+    return ret;
+    }
+
+void CFotaUpdate::RunL()
+    {
+    FLOG(_L("CFotaUpdate::RunL >>"));
+
+    if (iStatus.Int() == KErrNone)
+        {
+        TInt value = 0;
+
+        if (iMonitorType == BatteryLevel)
+            {
+            iProperty.Get(KPSUidHWRMPowerState, KHWRMBatteryLevel,
+                    value);
+
+            FLOG(_L("Battery level has changed to %d"), value);
+
+            iFotaServer->UpdateBatteryLowInfo(
+                    (value >= BatteryLevelAccepted) ? EFalse : ETrue);
+
+            MonitorBatteryChargeLevel();
+            }
+        else if (iMonitorType == ChargingStatus)
+            {
+            iProperty.Get(KPSUidHWRMPowerState, KHWRMChargingStatus,
+                    value);
+
+            FLOG(_L("Charging status has changed to %d"), value);
+
+            if (value == EChargingStatusCharging || value
+                    == EChargingStatusAlmostComplete || value
+                    == EChargingStatusChargingComplete || value
+                    == EChargingStatusChargingContinued)
+                {
+                if (IsUSBConnected())
+                    {
+                    ShowDialogL(EFwUpdNotEnoughBattery);
+                    }
+                else
+                    {
+                    iFotaServer->UpdateBatteryLowInfo(EFalse);
+                    }
+                }
+            else
+                {
+                iFotaServer->UpdateBatteryLowInfo(ETrue);
+                }
+            }
+
+        }
+    FLOG(_L("CFotaUpdate::RunL, iStatus = %d <<"), iStatus.Int());
+    }
+
+// ---------------------------------------------------------------------------
+// CFotaUpdate::StartUpdateL
+// Starts fw updating (shows a notifier to user). 
+// ---------------------------------------------------------------------------
+//
+void CFotaUpdate::StartUpdateL(const TDownloadIPCParams &aParams)
+    {
+    FLOG(_L("CFotaUpdate::StartUpdateL,  pkig:%d >>"), aParams.iPkgId);
+
+    //First cancel any ongoing battery monitoring.
+    CancelMonitor();
+
+    UpdateL();
+
+    FLOG(_L("CFotaUpdate::StartUpdateL <<"));
+    }
+
+TInt CFotaUpdate::RunError(TInt aError)
+    {
+    FLOG(_L("CFotaUpdate::RunError, error = %d >>"), aError);
+    return aError;
+    }
+
+void CFotaUpdate::DoCancel()
+    {
+    FLOG(_L("CFotaUpdate::DoCancel >>"));
+
+    iProperty.Cancel();
+
+    FLOG(_L("CFotaUpdate::DoCancel <<"));
+    }
+
+void CFotaUpdate::ShowDialogL(TFwUpdNoteTypes aDialogid)
+    {
+    FLOG(_L("CFotaUpdate::ShowDialogL, dialogid = %d >>"), aDialogid);
+    iFotaServer->ServerCanShut(EFalse);
+
+    if (iFotaServer->FullScreenDialog())
+        iFotaServer->FullScreenDialog()->Close();
+
+    iNotifParams = CHbSymbianVariantMap::NewL();
+
+    HBufC* keyDialog = HBufC::NewL(10);
+    CleanupStack::PushL(keyDialog);
+    *keyDialog = KKeyDialog;
+
+    CHbSymbianVariant* dialogId = CHbSymbianVariant::NewL(&aDialogid,
+            CHbSymbianVariant::EInt);
+    iNotifParams->Add(*keyDialog, dialogId);
+    iNotifier = CFotaDownloadNotifHandler::NewL(this);
+
+    iNotifier->LaunchNotifierL(iNotifParams, aDialogid);
+
+    CleanupStack::PopAndDestroy();
+    FLOG(_L("CFotaUpdate::ShowDialogL <<"));
+    }
+
+void CFotaUpdate::HandleDialogResponse(int response, TInt aDialogId)
+    {
+    FLOG(_L("CFotaUpdate::HandleDialogResponse, dialogid = %d response = %d >>"), aDialogId, response);
+
+    if (aDialogId == EFwUpdNotEnoughBattery)
+        {
+        iFotaServer->FinalizeUpdate();
+        }
+
+    FLOG(_L("CFotaUpdate::HandleDialogResponse <<"));
+    }
+
+TInt CFotaUpdate::WriteUpdateBitmapL( const TDesC& aText, const TDesC& aFile)
+    {
+    FLOG(_L("WriteUpdateBitmapL writing %S to %S w/ txtdir"),&aText,&aFile);
+
+    TSize   screensize = CCoeEnv::Static()->ScreenDevice()->SizeInPixels();
+    TInt                width  = screensize.iWidth - KBmpMargin*2;
+    TInt                height =  screensize.iHeight;
+
+    CArrayFixSeg<TPtrC>*   lines = new CArrayFixSeg<TPtrC>(5);
+    CleanupStack::PushL(lines);
+    CFbsBitmap*         bitmap = new ( ELeave ) CFbsBitmap;
+    CleanupStack::PushL( bitmap );
+    bitmap->Create(  TSize(width,height), EColor64K );
+    CFbsBitmapDevice*   device = CFbsBitmapDevice::NewL( bitmap );
+    CleanupStack::PushL( device );
+    const CFont* font = AknLayoutUtils::FontFromId(EAknLogicalFontPrimaryFont);
+    CFbsBitGc*          context;
+    User::LeaveIfError( device->CreateContext( context ) );
+    CleanupStack::PushL( context );
+    TInt                ascent = font->AscentInPixels();
+    TInt                descent = font->DescentInPixels();
+    context->UseFont ( font );
+    context->Clear(); // bg color
+
+    // Visually ordered text
+    HBufC* wrappedstring = AknBidiTextUtils::ConvertToVisualAndWrapToArrayL(
+            aText, width,*font, *lines);
+    CleanupStack::PushL ( wrappedstring );
+    TBool dirfound (ETrue);
+    // direction of text, affects alignemnt
+    TBidiText::TDirectionality direction = TBidiText::TextDirectionality(
+            *wrappedstring, &dirfound );
+
+    // Print visual text to bitmap
+    for ( TInt i=0; i<lines->Count(); ++i ) 
+        {
+        TPtrC l = (*lines)[i];
+        TInt top = (ascent+descent)*(i);
+        TInt bot = (ascent+descent)*(i+1);
+        TRect rect (0, top ,width, bot );
+        CGraphicsContext::TTextAlign alignment = 
+        direction==TBidiText::ELeftToRight ? CGraphicsContext::ELeft 
+            : CGraphicsContext::ERight;
+        context->DrawText(l, rect, ascent, alignment);
+        }
+    height = (ascent+descent)*lines->Count() + descent;
+    bitmap->Resize( TSize(width,height));
+    bitmap->Save( aFile );
+    context->DiscardFont();
+    CleanupStack::PopAndDestroy( wrappedstring );
+    CleanupStack::PopAndDestroy( context );
+    CleanupStack::PopAndDestroy( device );
+    CleanupStack::PopAndDestroy( bitmap );
+    CleanupStack::PopAndDestroy( lines );
+    return 1;
+    }