diff -r 3f419852be07 -r 364021cecc90 smartinstaller/adm/src/ADMAppUi.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/smartinstaller/adm/src/ADMAppUi.cpp Wed Jun 30 11:01:26 2010 +0530 @@ -0,0 +1,1483 @@ +/* +* Copyright (c) 2009-2010 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: +* CADMAppUi implementation +* +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include +#include // Phone information +#include // Hal::GetData() +#include // PathInfo:: +#include // SysUtil::DiskSpaceBelowCriticalLevel(), GetSWVersion() +#include // StringLoader::LoadLC() +#include +#include +#include // Default dialogs +#include +#include +#include "ADM.hrh" +#include "ADM.pan" +#include "ADMApplication.h" +#include "ADMAppUi.h" +#include "ADMStateMachine.h" +#include "ADMXmlParser.h" +#include "ADMSisParser.h" +#include "ADMPackageInfo.h" +#include "ADMDownloadHandler.h" +#include "ADMInstallManager.h" +#include "networkstatuslistener.h" + +#include "debug.h" +#include "globals.h" +#include "config.h" +#include "macros.h" +#include "utils.h" + +#ifdef USE_LOGFILE +_LIT(KADMLogDir, "ADM"); +_LIT(KADMLogFileName, "log.txt" ); +_LIT(KADMLogFile, "?:\\logs\\ADM\\log.txt"); +#endif + +/** + * Download path for dependency packages + */ +_LIT(KADMFolderPath,"?:\\system\\adm\\"); + +// ============================ MEMBER FUNCTIONS =============================== +void CADMAppUi::ConstructL() + { + LOG( "+ CADMAppUi::ConstructL()" ); + + // Hide from application task list + HideApplicationFromFSW(); + + // Initialise app UI with standard value. + BaseConstructL( ENoScreenFurniture /*CAknAppUi::EAknEnableSkin*/); + StatusPane()->MakeVisible(EFalse); + + // Set download path + TChar systemDrive; + RFs::DriveToChar(RFs::GetSystemDrive(), systemDrive); + HBufC* downloadPath = KADMFolderPath().AllocLC(); + downloadPath->Des()[0] = systemDrive; + + // Create the state machine + iStateMachine = CStateMachine::NewL(*this, *downloadPath); + + iRfs = iEikonEnv->FsSession(); + + iOviStoreRunning = CUtils::OviStoreRunning(); + + // Process command line arguments + ProcessCommandLineArgsL(); + + iProgress = CProgressDialog::NewL(*this); + + // If we don't have exit reason set, we can show the progress already + if (iExitReason == EExitNoError) + { + // Show progress bar with little progress already early on + const TInt waitNoteRes = iResumingInstallation + ? R_ADM_CONTINUING_INST_TEXT + : R_ADM_VERIFYING_SW_TEXT; + ShowGlobalProgressL( waitNoteRes, 1, 10 ); + } + + iSwVersion = HBufC::NewL(KSysUtilVersionTextLength); + + // Initialize the telephone server + User::LeaveIfError( iTelServer.Connect() ); + User::LeaveIfError( iTelServer.LoadPhoneModule( KMmTsyModuleName ) ); + User::LeaveIfError( iPhone.Open( iTelServer, KMmTsyPhoneName ) ); + + // Get device information + User::LeaveIfError( GetPhoneInformation() ); + + // Ignore the return code. Default URL will be used if error happens (leaves if no memory) + ReadConfigurationL(); + + ReadStaticResourcesL(); + + // Kick the state machine running + iStateMachine->Start(); + + CleanupStack::PopAndDestroy(downloadPath); + + LOG( "- CADMAppUi::ConstructL()" ); + } + +// ----------------------------------------------------------------------------- +// CADMAppUi::CADMAppUi() +// C++ default constructor can NOT contain any code, that might leave. +// ----------------------------------------------------------------------------- +// +CADMAppUi::CADMAppUi() : + iExitReason(EExitNoError), + iIAP(KInvalidIapId), + iIsResumeRequired(ETrue) + { + // disable possible transition effects + SetFullScreenApp(EFalse); + INIT_DEBUG_LOG( KADMLogFile(), KADMLogDir, KADMLogFileName ); + LOG( "CADMAppUi::CADMAppUi()" ); + // Restore our thread priority to normal, we have been launched + // with EPriorityBackground +// RThread().SetPriority(EPriorityNormal); + } + +// ----------------------------------------------------------------------------- +// CADMAppUi::~CADMAppUi() +// Destructor. +// ----------------------------------------------------------------------------- +// +CADMAppUi::~CADMAppUi() + { + LOG( "CADMAppUi::~CADMAppUi()" ); + + // Stop the state machine + iStateMachine->Stop(); + + // Just be make sure that all global stuff is out from the screen + CancelProgressBar(); + CancelWaitNote(); + + iPhone.Close(); + iTelServer.Close(); + + DELETE_IF_NONNULL( iQueryMessage ); + DELETE_IF_NONNULL( iGlobalConfirmationQuery ); + DELETE_IF_NONNULL( iGlobalQueryObserver ); + delete iAppIconFilename; + delete iMainAppName; + delete iConfigUrl; + delete iSwVersion; + delete iProgress; + delete iDepFileName; + delete iSisFileName; + delete iStateMachine; + + CLOSE_DEBUG_LOG; + } + +// ----------------------------------------------------------------------------- +// Processes the command line parameters and sets state machine initial +// state according to the parameters. +// +// Requires that the state machine has been instantiated (iStateMachine). +// ----------------------------------------------------------------------------- +// +void CADMAppUi::ProcessCommandLineArgsL() + { + LOG( "+ ProcessCommandLineArgsL()" ); + CCommandLineArguments* args = CCommandLineArguments::NewLC(); + const TInt count = args->Count(); + +#ifdef FEATURE_INSTALL_RESUME + // If ADM is launched from the menu, we don't get any command line parameters + // Need to read the info from the resume info file, if it exists. + if (count == 1) + { + CleanupStack::PopAndDestroy(args); + const TInt ret = ReadResumeInfoL(); + if (ret != KErrNone) + { + ShowGlobalNoteL(EAknGlobalErrorNote, R_ADM_ERR_NO_PENDING_INSTALLATIONS_TEXT); + ExitApp(); + } + iResumingInstallation = ETrue; + return; + } +#else + if (count == 1) + { + User::Leave( KErrNotSupported ); + } +#endif // FEATURE_INSTALL_RESUME + + // index to the command line args, starting at 1 (0 = executable name) + TInt index = 1; + +#ifdef DO_LOG + for (int i = 0; i < count; i++) + { + LOG3( "Arg[%d]='%S'", i, &(args->Arg(i)) ); + } +#endif + + TPtrC arg = args->Arg(index++); + TLex lex(arg); + TUint32 protocolVerRaw = 0; + TUint32 protocolVer = 0; + TUint32 tmp; + if ( lex.Val(protocolVerRaw, EDecimal) == 0) + { + LOG3( "(cmd) pVer(raw) = %d (%03x)", protocolVerRaw, protocolVerRaw ); + protocolVer = (protocolVerRaw & KCmdLineBitProtocolVerMask); + } + else + { + LOG( "Invalid P/BVersion, PANIC" ); + Panic(EPanicAdmCmdLineArgs); + } + + if (protocolVer < 15) + { + // assume it's old version without the bit field support + LOG2( "Using old args %d", protocolVer ); + + // Following are the command line args passed in the old version of Bootstrap: + // arg 0 - ADM.exe + // arg 1 - Bootstrap Version + // arg 2 - WrapperUid + // arg 3 - IAP + // arg 4 - Sisfilename + // arg 5 - Depfilename (optional) + + // Get the Bootstrap version + iBootstrapVersion = protocolVer; + LOG2("(cmd) BVersion: %x", iBootstrapVersion); + + // Get the Wrapper uid + TPtrC uidPtr = args->Arg(index++); + lex.Assign(uidPtr); + TUint32 uid = 0; + if ( lex.Val(uid, EDecimal ) == 0) + { + LOG2("(cmd) Wrapper Uid: 0x%x", uid); + + iWrapperPackageUid = TUid::Uid(uid); + } + + // See if at least the minimum options required are provided + if (count < 5) + { + LOG2( "Incorrect # of arguments (%d) passed from bootstrap, PANIC", count ); + Panic(EPanicAdmCmdLineArgs); + } + + // Get Iap + TPtrC iapPtr = args->Arg(index++); + lex.Assign(iapPtr); + if ( lex.Val(iIAP, EDecimal) == 0 ) + { + LOG2("(cmd) IAP: %d", iIAP); + iStateMachine->SetIAP(iIAP); + } + + switch (iBootstrapVersion) + { + case 1: + case 2: + { + if ( count != 6 ) + { + LOG2( "Incorrect # of arguments (%d) passed from bootstrap, PANIC", count ); + Panic(EPanicAdmCmdLineArgs); + } + iDepFileName = args->Arg(index++).AllocL(); + LOG2( "(cmd) DepFile: '%S'", iDepFileName); + + iSisFileName = args->Arg(index++).AllocL(); + LOG2( "(cmd) AppSis: '%S'", iSisFileName); + break; + } + case 3: + { + iDepFileName = args->Arg(index++).AllocL(); + LOG2( "(cmd) DepFile: '%S'", iDepFileName); + break; + } + case 4: + { + iSisFileName = args->Arg(index++).AllocL(); + LOG2( "(cmd) AppSis: '%S'", iSisFileName); + break; + } + default: + LOG2( "Invalid BVersion %d, PANIC", iBootstrapVersion ); + Panic(EPanicAdmCmdLineArgs); + break; + } + } + else if (protocolVer == 15) + { + LOG( "Using new args" ); + + // Command line arguments, version 15 specification: + // + //31 9 8 7 6 5 4 3 2 1 0 + // +-------------+--+--+--+--+--+--+--+--+--+--+ + // | reserved | | | | | | | | + // +-------------+--+--+--+--+--+--+--+--+--+--+ + // + // value + // bits range description + // 0-3 0-15 Command line parameter protocol version: + // 0 = not supported + // 1 = ADM.exe 1 + // 2 = ADM.exe 2 + // 3 = ADM.exe 3 + // 4 = ADM.exe 4 (this was used in beta1, beta2) + // 15 = ADM.exe 15 [parameters as specified by other bits] + // + // since + // bit version type command line parameter present + // 4 4 N Bootstrap version number + // 5 4 N Wrapper UID + // 6 4 N IAP + // 7 4 N ADM launch condition code: + // KCmdLineCancelAdm: ADM needs to cancel installation + // KCmdLineLaunchAdm: ADM starts normally + // 8 4 S Full path to dependency XML file + // 9 4 S Full path to application SIS file + // + // Types: + // N Natural decimal number (range 0 - 2^32-1, fits to TUint32) + // S UTF-8 string, must NOT contains spaces or other whitespaces + // + // Command line parameters appear in the order of the bits set, i.e. + // if bits 4, 8, 9 are set the command line parameters are: + // ADM.exe 784 + // + // If command line protocol version is less than 15, it is assumed that + // old version command line parameter format is used. + // + + // new version. bit fields define which parameters are present + // these has to be processed in the right order: from LSB to MSB + if (protocolVerRaw & KCmdLineBitBootstrapVersion) + { + TPtrC arg = args->Arg(index++); + lex.Assign(arg); + if ( lex.Val(iBootstrapVersion) == 0 ) + { + LOG2( "(cmd) BVersion: %x", iBootstrapVersion ); + } + else + { + LOG( "Invalid BVersion" ); + Panic(EPanicAdmCmdInvalidBootstrap); + } + } + if (protocolVerRaw & KCmdLineBitWrapperUid) + { + TPtrC arg = args->Arg(index++); + lex.Assign(arg); + if ( lex.Val(tmp, EDecimal) == 0 ) + { + LOG2("(cmd) Wrapper Uid: 0x%x", tmp); + iWrapperPackageUid = TUid::Uid(tmp); + } + else + { + LOG( "Invalid wrapper package UID" ); + Panic(EPanicAdmCmdInvalidWrapperUid); + } + } + if (protocolVerRaw & KCmdLineBitIAP) + { + TPtrC arg = args->Arg(index++); + lex.Assign(arg); + if ( lex.Val(iIAP, EDecimal) == 0 ) + { + LOG2("(cmd) IAP: %d", iIAP); + iStateMachine->SetIAP(iIAP); + } + else + { + LOG( "Invalid IAP" ); + Panic(EPanicAdmCmdInvalidIAP); + } + } + if (protocolVerRaw & KCmdLineBitADMLaunchControl) + { + TPtrC arg = args->Arg(index++); + lex.Assign(arg); + if ( lex.Val(tmp, EDecimal) == 0 ) + { + LOG2("(cmd) LState %d", tmp); + switch (tmp) + { + case KCmdLineLaunchAdm: + // this is valid, nothing needs to be done + break; + case KCmdLineCancelAdmNoResume: + iIsResumeRequired = EFalse; + // fall-through + case KCmdLineCancelAdm: + iStateMachine->SetStartState(CStateFactory::EStatePrepareExitWithError); + iStateMachine->SetFailureReason(EUserCancelled); + break; + default: + LOG2( "Invalid LState %d, PANIC", tmp ); + Panic(EPanicAdmCmdInvalidLaunchState2); + break; + } // switch + } + else + { + LOG( "Invalid LState, PANIC" ); + Panic(EPanicAdmCmdInvalidLaunchState); + } + } + if (protocolVerRaw & KCmdLineBitFileDep) + { + iDepFileName = args->Arg(index++).AllocL(); + LOG2( "(cmd) DepFile: '%S'", iDepFileName); + } + if (protocolVerRaw & KCmdLineBitFileSis) + { + iSisFileName = args->Arg(index++).AllocL(); + LOG2( "(cmd) SisFile: '%S'", iSisFileName); + } + } + else + { + LOG2( "Invalid PVersion %d, PANIC", protocolVer ); + Panic(EPanicAdmCmdInvalidProtocol); + } + CleanupStack::PopAndDestroy(args); + + LOG3( "- ProcessCommandLineArgsL(): %d->%d", count, index ); + } + +// ----------------------------------------------------------------------------- +// Read the information from the resume info file, if launched from the menu. +// ----------------------------------------------------------------------------- +// +TInt CADMAppUi::ReadResumeInfoL() + { + LOG( "+ ReadResumeInfo()" ); + RArray< TPtrC > lineBuffer; + TInt err = 0; + HBufC* buffer = ReadConfigFile( iRfs, KADMResumeInfoFile, lineBuffer, err ); + + if ( buffer && err == KErrNone ) + { + // Read the main application name + TPtrC namePtr = GetConfigValue( KRFieldAppName, lineBuffer, err ); + if ( err == KErrNone ) + { + iMainAppName = namePtr.AllocL(); + LOG2( "Resuming '%S'", iMainAppName ); + } + + // Get BootstrapVersion from the resume info file + TPtrC bootstrapVersionLine = GetConfigValue( KRFieldBootstrap, lineBuffer, err ); + if ( err == KErrNone ) + { + TLex lex(bootstrapVersionLine); + if ( lex.Val(iBootstrapVersion) == 0 ) + { + LOG2( "(resume) Version: %d", iBootstrapVersion ); + } + else + { + // TODO: Error: Can this ever happen?! + //LOG( "Incorrect version in the resume info" ); + return KErrNotSupported; + } + } + else + { + LOG2( "Failed to read version from the resume info (%d)", err ); + return err; + } + } + else + { + LOG( "! No resume information, cannot continue" ); + // Resume information file doesn't exist + return err; + } + + // Get the Wrapper uid + TPtrC uidPtr = GetConfigValue( KRFieldWrapperPkgUid, lineBuffer, err ); + if ( err == KErrNone ) + { + TLex lex(uidPtr); + TUint32 uid = 0; + if ( lex.Val(uid, EDecimal ) == 0) + { + LOG2( "Wrapper Uid: 0x%x", uid ); + iWrapperPackageUid = TUid::Uid(uid); + } + else + { + //LOG( "Incorrect wrapper UID in resume info" ); + return KErrNotSupported; + } + } + else + { + LOG2( "Failed to read wrapper UID from the resume info (%d)", err ); + return err; + } + + switch (iBootstrapVersion) + { + case 1: + case 2: + case 3: + { + // Get AppFileName from the resume information file + TPtrC depFileNameLine = GetConfigValue( KRFieldDepFileName, lineBuffer, err ); + if ( err == KErrNone ) + { + iDepFileName = depFileNameLine.AllocL(); + + LOG2( "(resume) DepFileName = '%S'", iDepFileName ); + + if ( !BaflUtils::FileExists(iRfs, *iDepFileName) ) + { + LOG2( "(resume) DepFile '%S' missing, cannot continue!", iDepFileName ); + return KErrNotFound; + } + } + else + { + LOG2( "Failed to read from the resume info (%d)", err ); + return err; + } + } + break; + case 4: + default: + break; + } + + switch (iBootstrapVersion) + { + case 1: + case 2: + case 4: + { + // Get AppFileName from the resume info file + TPtrC appFileNameLine = GetConfigValue( KRFieldAppFileName, lineBuffer, err ); + if ( err == KErrNone ) + { + iSisFileName = appFileNameLine.AllocL(); + + LOG2( "(resume) AppSis = '%S'", iSisFileName ); + + if ( !BaflUtils::FileExists(iRfs, *iSisFileName) ) + { + LOG2( "(resume) AppSis '%S' missing, cannot continue!", iSisFileName ); + return KErrNotFound; + } + } + else + { + LOG2( "Failed to read from the resume info (%d)", err ); + return err; + } + } + break; + case 3: + default: + break; + } + LOG2( "- ReadResumeInfo(): ret=%d", err ); + return err; + } + +// ----------------------------------------------------------------------------- +// Handles WindowServer events. Used to catch 'End Call' key. +// ----------------------------------------------------------------------------- +// +void CADMAppUi::HandleWsEventL( const TWsEvent& aEvent, CCoeControl* aDestination ) + { + if ( aEvent.Key()->iCode == EKeyPhoneEnd ) + { + iStateMachine->HandleUserResponse( EKeyPhoneEnd ); + } + else + { + CEikAppUi::HandleWsEventL( aEvent, aDestination ); + } + } + +// ----------------------------------------------------------------------------- +// CADMAppUi::HandleCommandL() +// Takes care of command handling. +// ----------------------------------------------------------------------------- +// +void CADMAppUi::HandleCommandL(TInt aCommand) + { + switch (aCommand) + { + case EEikCmdExit: + case EAknSoftkeyExit: + Exit(); + break; + + default: + Panic(EPanicAdmUi); + break; + } + } + +// ----------------------------------------------------------------------------- +// Callback CGlobalWaitNote +// +// Called when global wait note was cancelled +// ----------------------------------------------------------------------------- +// +void CADMAppUi::WaitNoteCancelled() + { + LOG2( "! Wait note cancelled (%d)", iStateMachine->StateIndex() ); + iStateMachine->HandleUserResponse( EAknSoftkeyCancel ); + } + +// ----------------------------------------------------------------------------- +// Callback CProgressDialog +// +// Called when progress dialog was cancelled +// ----------------------------------------------------------------------------- +// +void CADMAppUi::ProgressDialogCancelled() + { + LOG2( "! Progress dialog cancelled (%d)", iStateMachine->StateIndex() ); + iStateMachine->HandleUserResponse( EAknSoftkeyCancel ); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void CADMAppUi::HandleGlobalQueryResponseL(const TInt aResponse) + { + LOG2( "+ HandleGlobalQueryResponseL(): %d", aResponse ); + iStateMachine->HandleUserResponse( aResponse ); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void CADMAppUi::ShowDownloadQueryL(const TInt aResourceId, const TInt aInfoResourceId) + { + const TInt KMaxDownloadSizeMsg = 32; + + if ( iGlobalQueryObserver ) + { + iGlobalQueryObserver->Cancel(); + delete iGlobalQueryObserver; + iGlobalQueryObserver = NULL; + } + iGlobalQueryObserver = CGlobalQueryObserver::NewL(this, EFalse); + + DELETE_IF_NONNULL( iGlobalConfirmationQuery ); + DELETE_IF_NONNULL( iQueryMessage ); + iGlobalConfirmationQuery = CAknGlobalConfirmationQuery::NewL(); + + TBuf dlSizeDescr; + PrettyPrint( iStateMachine->TotalDownloadSize(), dlSizeDescr ); + + CDesCArrayFlat* strings = new (ELeave) CDesCArrayFlat(3); + CleanupStack::PushL(strings); + HBufC* msg = StringLoader::LoadLC( R_ADM_SW_UPDATE_REQUIRED_TEXT, iEikonEnv ); + HBufC* info; + if (aInfoResourceId != -1) + { + info = StringLoader::LoadLC( aInfoResourceId, iEikonEnv ); + } + else + { + info = KNullDesC().AllocLC(); + } + strings->AppendL(*msg); + strings->AppendL(*info); + strings->AppendL(dlSizeDescr); + iQueryMessage = StringLoader::LoadL( aResourceId, *strings, iEikonEnv ); + CleanupStack::PopAndDestroy(3, strings); // strings, msg, info + + // Cancel the progress dialog just before querying the user to reduce flicker + CancelProgressBar(); + + iGlobalConfirmationQuery->ShowConfirmationQueryL( + iGlobalQueryObserver->iStatus, + *iQueryMessage, + 0 + ); + iGlobalQueryObserver->Start(); +#if 0 + const TInt KMaxDownloadSizeMsg = 32; + TBuf dlSizeDescr; + PrettyPrint( iDepTree->GetTotalDownloadSize(), dlSizeDescr ); + HBufC* string = StringLoader::LoadLC( aResourceId, dlSizeDescr, iEikonEnv ); + + CAknQueryDialog* dlg = CAknQueryDialog::NewL(); + const TInt ret = dlg->ExecuteLD( R_AVKON_DIALOG_EMPTY_MENUBAR, *string ); + + CleanupStack::PopAndDestroy(); // string + + return ret; +#endif + } + +// ----------------------------------------------------------------------------- +// Shows the application launch query dialog +// @param aAppName Application name, caption, to be shown to the user +// @param aIconFilename Full path to the application icon, KNullDesC if none. +// ----------------------------------------------------------------------------- +// +void CADMAppUi::ShowLaunchPromptL(const TDesC& aAppName, const TDesC& aIconFilename) + { + if ( iGlobalQueryObserver ) + { + iGlobalQueryObserver->Cancel(); + delete iGlobalQueryObserver; + iGlobalQueryObserver = NULL; + } + iGlobalQueryObserver = CGlobalQueryObserver::NewL(this, EFalse); + + DELETE_IF_NONNULL( iGlobalConfirmationQuery ); + DELETE_IF_NONNULL( iQueryMessage ); + iGlobalConfirmationQuery = CAknGlobalConfirmationQuery::NewL(); + iQueryMessage = StringLoader::LoadL( R_ADM_LAUNCH_APP_TEXT, aAppName, iEikonEnv ); + iGlobalConfirmationQuery->ShowConfirmationQueryL( + iGlobalQueryObserver->iStatus, + *iQueryMessage, + 0, // Softkeys + 0, // Animation + aIconFilename, + EMbmAdmAdm, // BitmapId + EMbmAdmAdm_mask // MaskId + ); + iGlobalQueryObserver->Start(); + // Cancel the progress dialog and notes after creating the note to reduce flicker + CancelProgressBar(); + CancelWaitNote(); + } + +// ----------------------------------------------------------------------------- +// @param aType Global note type. +// @param aResourceId Resource ID to text to be displayed. +// ----------------------------------------------------------------------------- +// +TInt CADMAppUi::ShowGlobalNoteL( const TAknGlobalNoteType aType, const TInt aResourceId ) + { + // Allocate TBuf with constant length. + TBuf text( NULL ); + + // Do we have a valid resource ID for the note? + if (aResourceId != -1) + { + // Reads a resource into a descriptor. + iEikonEnv->ReadResourceL( text, aResourceId ); + + if ( iStateMachine->FailedState() == CStateFactory::EStateLast && + iExitReason != EExitNoError) + { + const TInt error = iStateMachine->FailedState() * 100 + iExitReason; + text.Append('\n'); + text.AppendNum( error ); + } + + // Cancel any progress dialog + CancelProgressBar(); + // Cancel any wait notes + CancelWaitNote(); + + if (aType == EAknGlobalErrorNote ) + { + CAknQueryDialog* dlg = CAknQueryDialog::NewL( CAknQueryDialog::EErrorTone ); + return dlg->ExecuteLD( R_ADM_EXIT_QUERY, text ); + } + else + { + // Create new CAknGlobalNote instance. + CAknGlobalNote* globalNote = CAknGlobalNote::NewLC(); + globalNote->ShowNoteL( aType, text ); + CleanupStack::PopAndDestroy(globalNote); + } + } + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// Shows the exit note with information, how the interrupted/cancelled installation +// can be continued. +// ----------------------------------------------------------------------------- +// +TInt CADMAppUi::ShowExitNoteL() + { + TInt ret = KErrNone; + // The order of this table must match TExitReason order + static const TInt errorNotes[ELastExitState] = { +/* EExitNoError 0 */ -1, +/* EUserCancelled 1 */ -1, //R_ADM_INST_CAN_BE_RESUMED_TEXT, +/* EDownloadFailed 2 */ R_ADM_ERR_DOWNLOAD_FAILED_TEXT, +/* EInsufficientMemory 3 */ R_ADM_ERR_INSTALLATION_NOT_ENOUGH_SPACE_TEXT, +/* EDeviceNotSupported 4 */ R_ADM_ERR_INSTALLATION_UNSUPPORTED_DEVICE_TEXT, +/* EInstallationFailed 5 */ R_ADM_ERR_INSTALLATION_FAILED_TEXT, +/* ERootInstallationFailed */ -1 + }; + + // First, show an error note describing what went wrong + if (errorNotes[iExitReason] > 0) + { + CAknErrorNote* note = new (ELeave) CAknErrorNote( ETrue ); + HBufC* msg = StringLoader::LoadLC( errorNotes[iExitReason], iEikonEnv ); + note->ExecuteLD( *msg ); + CleanupStack::PopAndDestroy(); // msg + } + + if (iExitReason != EDeviceNotSupported) + { + // Then show the "installation can be continued later" information + // but only if the device is a supported one. + CAknQueryDialog* dlg = CAknQueryDialog::NewL( CAknQueryDialog::EErrorTone ); + HBufC* oviMsg = NULL; + if (iOviStoreRunning) + { + // TODO: Change ADM so root node would always contain the main application sis information + HBufC* caption = iStateMachine->LaunchCaption(); + if (!caption) + { + caption = KNullDesC().AllocL(); + } + oviMsg = StringLoader::LoadLC( + R_ADM_INST_CAN_BE_RESUMED_OVI_TEXT, + *caption, + iEikonEnv + ); + } + else + { + oviMsg = KNullDesC().AllocLC(); + } + HBufC* mainMsg = StringLoader::LoadLC( + R_ADM_INST_CAN_BE_RESUMED_TEXT, + *oviMsg, + iEikonEnv + ); + ret = dlg->ExecuteLD( R_ADM_EXIT_QUERY, *mainMsg ); + CleanupStack::PopAndDestroy(2, oviMsg); + } + return ret; + } + +// ----------------------------------------------------------------------------- +// Creates a wait note displaying given resource ID. +// @param aResourceId Resource ID to be shown +// @param aCancellable ETrue, if wait note is cancellable +// @param aDetailedResourceId Additional resource ID to be shown, -1 if none +// ----------------------------------------------------------------------------- +// +void CADMAppUi::ShowWaitNoteL( const TInt aResourceId, + const TBool aCancellable, + const TInt aDetailedResourceId + ) + { + TBuf resourceMsg; + CancelWaitNote(); + + if (aDetailedResourceId != -1) + { + iEikonEnv->ReadResourceL( resourceMsg, aDetailedResourceId ); + HBufC* msg = StringLoader::LoadL( aResourceId, resourceMsg, iEikonEnv ); + resourceMsg.Copy( *msg ); + delete msg; + } + else + { + iEikonEnv->ReadResourceL( resourceMsg, aResourceId ); + } + + iWaitNote = CGlobalWaitNote::NewL(*this, aCancellable ); + iWaitNote->ShowNoteL( resourceMsg ); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void CADMAppUi::ShowWaitNoteNumL( const TInt aResourceId, const TInt aCurrent, const TInt aLast) + { + CancelWaitNote(); + + CArrayFix* vals = new (ELeave) CArrayFixFlat(2); + CleanupStack::PushL(vals); + vals->AppendL(aCurrent); + vals->AppendL(aLast); + HBufC* msg = StringLoader::LoadLC( aResourceId, *vals, iEikonEnv ); + + iWaitNote = CGlobalWaitNote::NewL( *this, ETrue ); + iWaitNote->ShowNoteL( *msg ); + + CleanupStack::PopAndDestroy(2, vals); + } + +// ----------------------------------------------------------------------------- +// Removes currently shown wait note. +// -----------------------------------------------------------------------------// +// +void CADMAppUi::CancelWaitNote() + { + if ( iWaitNote ) + { + TRAP_IGNORE( iWaitNote->CancelNoteL() ); + delete iWaitNote; + iWaitNote = NULL; + } + } + +// ----------------------------------------------------------------------------- +// Removes currently shown progress bar. +// -----------------------------------------------------------------------------// +// +void CADMAppUi::CancelProgressBar() + { + if ( iProgress ) + { + iProgress->Cancel(); + } + } + +// ----------------------------------------------------------------------------- +// ShowGlobalProgressL() +// +// aResourceId Resource ID of the text to be shown on the progress bar +// aStartValue Progress bar start value +// aEndValue Progress bar end value +// aCurrent Resource string value0 +// aLast Resource string value1 +// ----------------------------------------------------------------------------- +// +void CADMAppUi::ShowGlobalProgressL(const TInt aResourceId, + const TInt aStartValue, const TInt aEndValue, + const TInt aCurrent, const TInt aLast) + { + HBufC *msg = NULL; + CArrayFix* vals = new (ELeave) CArrayFixFlat(2); + CleanupStack::PushL(vals); + + if (aCurrent != -1) + { + vals->AppendL(aCurrent); + vals->AppendL(aLast); + + // Read the resource + msg = StringLoader::LoadLC( aResourceId, *vals, iEikonEnv ); + } + else + { + // Read the resource + msg = iEikonEnv->AllocReadResourceLC( aResourceId ); + + // Special case: append the application name to the string + if (aResourceId == R_ADM_CONTINUING_INST_TEXT) + { + if (iMainAppName && iMainAppName->Length() > 0) + { + HBufC* newmsg = HBufC::NewL(msg->Length() + iMainAppName->Length() + 3); + newmsg->Des().Copy(*msg); + newmsg->Des().Append('\n'); + newmsg->Des().Append('\''); + newmsg->Des().Append(*iMainAppName); + newmsg->Des().Append('\''); + CleanupStack::PopAndDestroy(msg); + msg = newmsg; + CleanupStack::PushL(msg); + } + } + } + + iProgress->Cancel(); + iProgress->StartL( *msg, aEndValue ); + iProgress->Update(aStartValue, aEndValue); + + CleanupStack::PopAndDestroy(2, vals); // msg, vals + } + +// ----------------------------------------------------------------------------- +// Shows a proper wait note before the cleanup starts. +// +// This function MUST NOT LEAVE. +// ----------------------------------------------------------------------------- +// +void CADMAppUi::HandleFailure() + { + LOG3( "+ CADMAppUi::HandleFailure(): %d. err=%d", iStateMachine->StateIndex(), iExitReason); + // Disable wait note and progress bar, if any + CancelProgressBar(); + CancelWaitNote(); + + // Delete the dep file + if ( iDepFileName ) + { + // We need to ignore, if delete leaves as we are currently already + // handling an error case. + // TODO: Remove if(), DeleteFile() copes with NULL filenames. + DeleteFile( *iDepFileName ); + // TODO: Should we 'delete iDepFileName;' and set it to NULL? + } + TInt err = KErrNone; + TInt waitNoteResource; + TInt detailedInfoResource = -1; + + switch (iExitReason) + { + case EDownloadFailed: + waitNoteResource = R_ADM_DETAILED_CANCELLING_INSTALLATION_WAIT_TEXT; + detailedInfoResource = R_ADM_ERR_CONN_LOST_TEXT; + break; + case EUserCancelled: + case EInstallationFailed: + waitNoteResource = R_ADM_CANCELLING_INSTALLATION_WAIT_TEXT; + break; + default: + waitNoteResource = R_ADM_REVERTING_CHANGES_WAIT_TEXT; + break; + } + + // Do the cleanup depending on the state that experienced failure + if ( iStateMachine->FailedState() >= CStateFactory::EStateDownloadChangesFile ) + { + TRAP(err, ShowWaitNoteL( waitNoteResource, EFalse, detailedInfoResource )); + } + + LOG2( "- CADMAppUi::HandleFailure(): %d", err ); + } + +// ----------------------------------------------------------------------------- +// Shows the final error message and exits application +// ----------------------------------------------------------------------------- +// +void CADMAppUi::ExitApp() + { + LOG3( "+ CADMAppUi::ExitApp(): %d, %d", iExitReason, iAppLaunch ); + + // Remove any progress bar + CancelProgressBar(); + // Remove any wait note + CancelWaitNote(); + + // Just checking that iExitReason is in the proper range + if ( iExitReason >= 0 && iExitReason < ELastExitState ) + { + // If we have an additional note to display, show it. We need to + // trap any leaves. + TRAP_IGNORE( + { + if ( iSilentInstallationOk && iExitReason == EExitNoError ) + { + // If we used non-silent installation, the "Installation complete" note + // was already shown by S60 Installer. Don't show it here again. + // If the user has launched the application, don't show the note + if (!iNonSilentInstallation && !iAppLaunch) + { + ShowGlobalNoteL( EAknGlobalConfirmationNote, R_ADM_INSTALLATION_OK_TEXT ); + // We need to wait 350ms to show the note as the call to Exit() below would kill + // the AppUi and also the note. + User::After(350000); + } + } + else + { + if (!iNonSilentInstallation) + { + // Show ADM again in task list. This is because we're using + // CAknQueryDialog: we don't want that to get hidden. + HideApplicationFromFSW(EFalse); + // This call returns after user has dismissed the error dialog + ShowExitNoteL(); + } + } + } + ); + } +#ifdef _DEBUG + else + { + LOG2( "Invalid exit reason %d", iExitReason ); + User::Invariant(); + } +#endif + + // Set the ADM icon hidden, if everything went smoothly or any resume info file exists. + const TBool hideAdm = !( (iExitReason != EExitNoError || iExitReason == EDeviceNotSupported) && iIsResumeRequired ); + const TInt err = CUtils::HideApplicationFromMenu( KUidADMApp.iUid, hideAdm ); + LOG3( "ADM icon hidden: %d (%d)", hideAdm, err ); + + RunAppShutter(); + Exit(); + + LOG( "- CADMAppUi::ExitApp()" ); + } + +// ----------------------------------------------------------------------------- +// Delete a file pointed by aFilename. +// ----------------------------------------------------------------------------- +// +void CADMAppUi::DeleteFile(const TDesC& aFilename) + { + iRfs.Delete(aFilename); + } + +// ----------------------------------------------------------------------------- +// Pretty prints number as text string using KiB, MiB and GiB prefixes when needed. +// +// aSize Number to pretty print. Only positive integers supported. +// aDescr Descriptor holding the pretty printed number string. +// ----------------------------------------------------------------------------- +// +void CADMAppUi::PrettyPrint(const TUint32 aSize, TDes& aDescr) + { + _LIT(KFmtDecimals, "%02d"); + TLocale locale; + TUint32 size = aSize, rem; + TPtrC sizePrefix( iPrefixKb ); + + // We don't pretty print bytes because "bytes" would a new string + // to localize. This is just to minimize that work. + if (aSize < 1024*1024) + { + size /= 1024; + rem = (aSize * 100 / 1024) % 100; + } + else if (aSize < 1024*1024*1024) + { + size /= 1024*1024; + rem = (aSize * 100 / (1024*1024)) % 100; + sizePrefix.Set( iPrefixMb ); + } + else + { + // TInt64 is needed, because aSize*100 will overflow on big values of aSize + TInt64 remBig( aSize ); + remBig = ((remBig * 100) / (1024*1024*1024)) % 100; + rem = remBig; + size /= 1024*1024*1024; + sizePrefix.Set( iPrefixGb ); + } + + aDescr.Num(size); + // Add decimals only if they != .00 + if (rem) + { + aDescr.Append(locale.DecimalSeparator()); + aDescr.AppendFormat(KFmtDecimals, rem); + } +// if (aSize > 999) +// aDescr.Insert(aDescr.Length() - 6, iLocale.ThousandsSeparator()); + aDescr.Append(sizePrefix); +} + +// ----------------------------------------------------------------------------- +// Gets detailed phone information and stores it internally. +// +// Returns KErrNone, if fetching of machine UID was succesful +// ----------------------------------------------------------------------------- +// +TInt CADMAppUi::GetPhoneInformation() + { + LOG( "+ GetPhoneInformation()" ); + + //TODO: Remove unnecessary information, currently MachineUid is only needed + TInt r = HAL::Get(HALData::EMachineUid, iMachineUid); +#if _DEBUG + HAL::Get(HALData::EManufacturer, iManufacturer); + HAL::Get(HALData::EManufacturerHardwareRev, iHardwareRev); + HAL::Get(HALData::EManufacturerSoftwareRev, iSoftwareRev); + HAL::Get(HALData::EModel, iModel); + HAL::Get(HALData::EDeviceFamily, iDeviceFamily); + HAL::Get(HALData::EDeviceFamilyRev, iDeviceFamilyRev); + HAL::Get(HALData::ECPUArch, iCpuArch); + HAL::Get(HALData::ECPUABI, iCpuABI ); + HAL::Get(HALData::ECPUSpeed, iCpuSpeed ); +#endif + TPtr swVer(iSwVersion->Des()); + SysUtil::GetSWVersion(swVer); + + LOG8_2( " machine uid = 0x%08x", iMachineUid); +#if _DEBUG + LOG8_2( " model = 0x%08x", iModel); + LOG8_2( " manufacturer = %d", iManufacturer); + LOG8_2( " hardware rev = %d", iHardwareRev); + LOG8_2( " software rev = %d", iSoftwareRev); + LOG8_2( " device family = %d", iDeviceFamily); + LOG8_2( " device family rev = %d", iDeviceFamilyRev); + LOG8_2( " CPU architecture = 0x%08x", iCpuArch); + LOG8_2( " CPU ABI = %d", iCpuABI); + LOG8_2( " CPU speed = %d", iCpuSpeed); +#endif + LOG2(" Sw Ver = %S", iSwVersion); + + LOG8_2( "- GetPhoneInformation (%d)", r); + + return r; + } + +// ----------------------------------------------------------------------------- +// Returns true if the phone is roaming +// ----------------------------------------------------------------------------- +// +TBool CADMAppUi::RegisteredRoaming() + { + LOG( "+ RegisteredRoaming()" ); + // Get registeration status + TRequestStatus status; + TInt ret = EFalse; // Default to not roaming + + RMobilePhone::TMobilePhoneRegistrationStatus regStatus( + RMobilePhone::ERegistrationUnknown ); + iPhone.GetNetworkRegistrationStatus( status, regStatus ); + User::WaitForRequest( status ); + + if ( RMobilePhone::ERegisteredRoaming == regStatus ) + { + ret = ETrue; + } + + LOG2( "- RegisteredRoaming: %d", ret ); + + return ret; + } +#if 0 +// --------------------------------------------------------------------------- +// CADMAppUi::PhoneMemoryDrive +// +// @return Drive number for phone memory. +// --------------------------------------------------------------------------- +// +TInt CADMAppUi::PhoneMemoryDrive() + { + TInt res = 0; + TInt err = RFs::CharToDrive( PathInfo::PhoneMemoryRootPath()[0], res ); + __ASSERT_ALWAYS( !err, Panic( EPanicAdmFileSystemAccess ) ); + + return res; + } + +// --------------------------------------------------------------------------- +// CADMAppUi::MemoryCardDrive +// +// @return Drive number for memory card. +// --------------------------------------------------------------------------- +// +TInt CADMAppUi::MemoryCardDrive() + { + TInt res = 0; + TInt err = RFs::CharToDrive( PathInfo::MemoryCardRootPath()[0], res ); + __ASSERT_ALWAYS( !err, Panic( EPanicAdmFileSystemAccess ) ); + + return res; + } +#endif +// --------------------------------------------------------------------------- +// CADMAppUi::ReadStaticResourcesL +// +// @return KErrNone if configuration was read correctly, error code otherwise +// --------------------------------------------------------------------------- +// +void CADMAppUi::ReadStaticResourcesL() + { + iEikonEnv->ReadResourceL( iPrefixKb, R_KB ); + iEikonEnv->ReadResourceL( iPrefixMb, R_MB ); + iEikonEnv->ReadResourceL( iPrefixGb, R_GB ); + } + +// --------------------------------------------------------------------------- +// CADMAppUi::UsingWLAN +// +// @return ETrue, if selected bearer is WLAN +// --------------------------------------------------------------------------- +// +TBool CADMAppUi::UsingWLAN() + { + return BearerType() == EBearerWLAN; + } + +// --------------------------------------------------------------------------- +// CADMAppUi::CheckBearerTypeL +// +// @return Bearer type +// --------------------------------------------------------------------------- +// +TInt CADMAppUi::BearerType() + { + LOG2( "+ BearerType(): IAP=%d", iIAP ); + RConnectionMonitor monitor; + TRequestStatus status = KRequestPending; + TUint iapId(0); + TInt bearer( 0 ); + TUint count; + TUint ids[ 15 ]; + + TRAPD( err, monitor.ConnectL() ); + if (err != KErrNone ) + { + LOG2( "BearerType: Connect to RConnMon failed. %d", err ); + return err; + } + + // Get the connection count + monitor.GetConnectionCount( count, status ); + User::WaitForRequest( status ); + if ( status.Int() != KErrNone ) + { + LOG2( "GetConnCount failed. %d", status.Int() ); + monitor.Close(); + return status.Int(); + } +#ifdef DO_LOG + else + { + LOG2( "BearerType: %d connections:", count); + } +#endif + + // Get the connection info for each connection + TUint numSubConnections; + TInt i; + + for ( i = 1; i <= count; i++ ) + { + TInt ret = monitor.GetConnectionInfo( i, ids[ i-1 ], numSubConnections ); + if ( ret == KErrNone ) + { + LOG3( "BearerType: ConnID[%d] = %d" , i, ids[ i-1 ] ); + // Get the IAP Id of the connection + monitor.GetUintAttribute( ids[ i-1 ], 0, KIAPId, iapId, status ); + User::WaitForRequest( status ); + if ( status.Int() != KErrNone ) + { + LOG2( "GetIapId failed. %d", status.Int() ); + // try next connection + continue; + } +#ifdef DO_LOG + else + { + LOG3( "BearerType: IapId = %d, IAP = %d", iapId, iIAP ); + } +#endif + // If the IAP matches with the one set in ADM + // iIAP is initialized to KInvalidIapId + if ( iapId == iIAP || iIAP == KInvalidIapId ) + { +#ifdef DO_LOG + LOG2( "BearerType: Getting bearer for IapId %d", iapId ); +#endif + // Get the Bearer of the IAP Id. + monitor.GetIntAttribute( ids[ i-1 ], 0, KBearer, bearer, status ); + User::WaitForRequest( status ); + if ( status.Int() != KErrNone ) + { + LOG2( "BearerType: GetBearerType failed. %d", status.Int() ); + // try next connection + continue; + } +#ifdef DO_LOG + else + { + LOG3( "BearerType: IapId %d: bearer = %d", iapId, bearer ); + } +#endif + // we found matching IAP ID, break out of the loop + break; + } + } + else + { + LOG2( "GetConnInfo failed. %d", ret ); + return ret; + } + } + TBuf iapName; + + // Get the string attrib of the IAP Id + monitor.GetStringAttribute( ids[ i-1 ], 0, KIAPName, iapName, status ); + User::WaitForRequest( status ); + if ( status.Int() != KErrNone ) + { + LOG2( "BearerType: GetStrAttr failed. %d", status.Int() ); + } + else + { + LOG5( "* Selected IAP %d (%d), conn %d '%S'", iapId, bearer, ids[i-1], &iapName ); + } + + // Close the RConnMon object + monitor.Close(); + + LOG2( "- BearerType(): %d", bearer ); + + return bearer; + } + +// --------------------------------------------------------------------------- +// CADMAppUi::ReadConfiguration +// +// @return KErrNone if configuration was read correctly, error code otherwise +// --------------------------------------------------------------------------- +// +TInt CADMAppUi::ReadConfigurationL() + { + TFileName configFile; + RArray< TPtrC > lineBuffer; + TInt ret( KErrNone ); + + // Find the configuration file from the private directory + ret = iRfs.PrivatePath(configFile); + if (ret == KErrNone) + { + TBuf<2> appDrive; + // Insert the drive of the running application + appDrive.Copy(Application()->AppFullName().Left(2)); + configFile.Insert(0, appDrive); + // Append the configuration file name + configFile.Append(KConfigFile); + + LOG2( "configFile = %S", &configFile ); + + HBufC* buffer = ReadConfigFile(iRfs, configFile, lineBuffer, ret ); + + if ( buffer && ret == KErrNone ) + { + TPtrC line = GetConfigValue( KCfgTagUrl, lineBuffer, ret ); + if ( ret == KErrNone ) + { + iConfigUrl = HBufC8::NewL(line.Length()); + iConfigUrl->Des().Copy(line); + LOG8_2( "configUrl = %S", iConfigUrl ); + } + delete buffer; + } + } + if ( !iConfigUrl ) + { + // Error occured while reading the configuration, use default URL + iConfigUrl = HBufC8::NewL(KDefaultDepServerUrl().Length()); + *iConfigUrl = KDefaultDepServerUrl; + LOG8_2( "configUrl = %S (default)", iConfigUrl ); + } + + lineBuffer.Close(); + + return ret; + } + +// End of File