--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/fotaapplication/fotaserver/src/fotaupdate.cpp Tue Jul 13 09:51:41 2010 +0530
@@ -0,0 +1,718 @@
+/*
+ * 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;
+ }