diff -r 13d7c31c74e0 -r b183ec05bd8c fotaapplication/fotaserver/src/fotaupdate.cpp --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fotaupdate.h" +#include "fmsclient.h" +#include "FotasrvSession.h" +#include "fotaserverPrivateCRKeys.h" +#include "fotaserverPrivatePSKeys.h" +#include "fotanotifiers.h" + +#include +#include +// ============================= 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 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 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 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* lines = new CArrayFixSeg(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; iCount(); ++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; + }