|
1 /* |
|
2 * Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * State machine implementation |
|
16 * |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 #include <ADM.rsg> |
|
22 #include "ADMApplication.h" // KUidADMApp |
|
23 #include "ADMStateMachine.h" |
|
24 #include "ADMStateMachineDebug.h" |
|
25 #include "globals.h" |
|
26 #include "config.h" |
|
27 |
|
28 #include <e32std.h> |
|
29 #include <sysutil.h> // SysUtil::DiskSpaceBelowCriticalLevel() |
|
30 #include <BAUTILS.H> |
|
31 #include <apgcli.h> |
|
32 |
|
33 // Use Char 0xFF to indicate no drive is selected |
|
34 const TChar KNoDriveSelected = 0xFF; |
|
35 |
|
36 // Used to force the progress bar to finish |
|
37 const TInt KProgressBarFullValue = 100; |
|
38 |
|
39 TInt CompareVersions(TVersion& version1, TVersion& version2); |
|
40 |
|
41 // --------------------------------------------------------------------------- |
|
42 // Panic |
|
43 // |
|
44 // Raises a panic with specific panic code. |
|
45 // --------------------------------------------------------------------------- |
|
46 // |
|
47 LOCAL_C inline void Panic(TInt aPanicCode) |
|
48 { |
|
49 _LIT(KPanic, "SmartInst-SM"); |
|
50 User::Panic( KPanic, aPanicCode ); |
|
51 } |
|
52 |
|
53 LOCAL_C inline void Panic(TInt aPanicCode, TInt aState) |
|
54 { |
|
55 _LIT(KPanic, "SmartInst-SM"); |
|
56 const TInt reason = aState*100 + aPanicCode; |
|
57 User::Panic( KPanic, reason ); |
|
58 } |
|
59 |
|
60 // ----------------------------------------------------------------------------- |
|
61 // Default constructor |
|
62 // ----------------------------------------------------------------------------- |
|
63 // |
|
64 CStateMachine::CStateMachine(CADMAppUi& aAppUi) : |
|
65 CActive(EPriorityNormal), |
|
66 iAppUi(aAppUi), |
|
67 iFailedState( CStateFactory::EStateLast ) |
|
68 { |
|
69 CActiveScheduler::Add(this); |
|
70 } |
|
71 |
|
72 // ----------------------------------------------------------------------------- |
|
73 // NewL() |
|
74 // ----------------------------------------------------------------------------- |
|
75 // |
|
76 CStateMachine* CStateMachine::NewL(CADMAppUi& aAppUi, const TDesC& aDownloadPath) |
|
77 { |
|
78 CStateMachine* self = new (ELeave) CStateMachine(aAppUi); |
|
79 CleanupStack::PushL(self); |
|
80 self->ConstructL(aDownloadPath); |
|
81 CleanupStack::Pop(); |
|
82 return self; |
|
83 } |
|
84 |
|
85 // ----------------------------------------------------------------------------- |
|
86 // ConstructL() |
|
87 // ----------------------------------------------------------------------------- |
|
88 // |
|
89 void CStateMachine::ConstructL(const TDesC& aDownloadPath) |
|
90 { |
|
91 // Create a local semaphore for handling the download deleting |
|
92 // This must be the first to be created and last to be destroyed. |
|
93 iDlDeletingSemaphore.CreateLocal(0); |
|
94 |
|
95 iXmlParser = CXmlParser::NewL(); |
|
96 iSisParser = CSisParser::NewL(); |
|
97 |
|
98 #ifdef USE_LOGFILE |
|
99 iInstallManager = CInstallManager::NewL(this, iAppUi.iLog); |
|
100 iDepTree = CDepTree::NewL(iAppUi.iLog, aDownloadPath); |
|
101 iDownloadHandler = CDownloadHandler::NewL(this, iAppUi.iLog, !(iAppUi.EikonEnv()->StartedAsServerApp())); |
|
102 #else |
|
103 iInstallManager = CInstallManager::NewL(this); |
|
104 iDepTree = CDepTree::NewL(aDownloadPath); |
|
105 iDownloadHandler = CDownloadHandler::NewL(this, !(iAppUi.EikonEnv()->StartedAsServerApp())); |
|
106 #endif |
|
107 |
|
108 iStateFactory = CStateFactory::NewL(*this); |
|
109 } |
|
110 |
|
111 // ----------------------------------------------------------------------------- |
|
112 // Destructor |
|
113 // ----------------------------------------------------------------------------- |
|
114 // |
|
115 CStateMachine::~CStateMachine() |
|
116 { |
|
117 if (IsActive()) |
|
118 { |
|
119 Cancel(); |
|
120 } |
|
121 delete iStateFactory; |
|
122 delete iDownloadHandler; |
|
123 delete iInstallManager; |
|
124 delete iDepTree; |
|
125 delete iSisParser; |
|
126 delete iXmlParser; |
|
127 delete iDownloadedFile; |
|
128 |
|
129 iDlDeletingSemaphore.Close(); |
|
130 } |
|
131 |
|
132 // ----------------------------------------------------------------------------- |
|
133 // Updates the displayed progress bar |
|
134 // ----------------------------------------------------------------------------- |
|
135 // |
|
136 void CStateMachine::UpdateProgressBar(TInt aStartValue, TInt aEndValue) |
|
137 { |
|
138 iAppUi.iProgress->Update(aStartValue, aEndValue); |
|
139 } |
|
140 |
|
141 // ----------------------------------------------------------------------------- |
|
142 // Removes the displayed progress bar |
|
143 // ----------------------------------------------------------------------------- |
|
144 // |
|
145 void CStateMachine::StopProgressBar() const |
|
146 { |
|
147 iAppUi.iProgress->Cancel(); |
|
148 } |
|
149 |
|
150 // ----------------------------------------------------------------------------- |
|
151 // Sets the failure state and reason for exit |
|
152 // ----------------------------------------------------------------------------- |
|
153 // |
|
154 void CStateMachine::SetFailureReason(TExitReason aReason) |
|
155 { |
|
156 iAppUi.iExitReason = aReason; |
|
157 iFailedState = (CStateFactory::TAppState)StateIndex(); |
|
158 // If the device is not supported, don't create resume info |
|
159 if (aReason == EDeviceNotSupported) |
|
160 { |
|
161 iAppUi.iIsResumeRequired = EFalse; |
|
162 } |
|
163 } |
|
164 |
|
165 // ----------------------------------------------------------------------------- |
|
166 // Shows the download query dialog with a specified text. |
|
167 // @param aResourceId Resource ID for the text to be shown. |
|
168 // @param aInfoResourceId Resource ID for additional information text. |
|
169 // ----------------------------------------------------------------------------- |
|
170 // |
|
171 void CStateMachine::ShowDownloadQueryL(const TInt aResourceId, const TInt aInfoResourceId) |
|
172 { |
|
173 iAppUi.ShowDownloadQueryL( aResourceId, aInfoResourceId ); |
|
174 } |
|
175 |
|
176 // ----------------------------------------------------------------------------- |
|
177 // Shows wait note |
|
178 // ----------------------------------------------------------------------------- |
|
179 // |
|
180 void CStateMachine::ShowWaitNoteL(const TInt aResourceId) |
|
181 { |
|
182 iAppUi.ShowWaitNoteL( aResourceId, ETrue ); |
|
183 } |
|
184 |
|
185 // ----------------------------------------------------------------------------- |
|
186 // Shows wait note with the specified values |
|
187 // ----------------------------------------------------------------------------- |
|
188 // |
|
189 void CStateMachine::ShowInstallingWaitNoteL(const TInt aCurrent, const TInt aLast) |
|
190 { |
|
191 iAppUi.ShowWaitNoteNumL( R_ADM_INSTALLING_TEXT, aCurrent, aLast ); |
|
192 } |
|
193 |
|
194 // ----------------------------------------------------------------------------- |
|
195 // Shows the progress bar with the specified values |
|
196 // ----------------------------------------------------------------------------- |
|
197 // |
|
198 void CStateMachine::ShowProgressBarL(const TInt aStartValue, const TInt aEndValue, const TInt aCurrent, const TInt aLast) |
|
199 { |
|
200 iAppUi.ShowGlobalProgressL( R_ADM_DOWNLOADING_TEXT, |
|
201 aStartValue, aEndValue, |
|
202 aCurrent, aLast ); |
|
203 } |
|
204 |
|
205 // ----------------------------------------------------------------------------- |
|
206 // Stops the wait note |
|
207 // ----------------------------------------------------------------------------- |
|
208 // |
|
209 void CStateMachine::StopWaitNote() |
|
210 { |
|
211 iAppUi.CancelWaitNote(); |
|
212 } |
|
213 |
|
214 // ----------------------------------------------------------------------------- |
|
215 // Starts the state machine from the initial state. |
|
216 // ----------------------------------------------------------------------------- |
|
217 // |
|
218 void CStateMachine::Start() |
|
219 { |
|
220 LOG( "+ CStateMachine::Start()" ); |
|
221 |
|
222 // If the initial state has been set, don't change it here |
|
223 if (!iState) |
|
224 { |
|
225 iState = &iStateFactory->GetState( CStateFactory::EStateSetup ); |
|
226 } |
|
227 |
|
228 iStatus = KRequestPending; |
|
229 SetActive(); |
|
230 // send signal that this request has completed |
|
231 TRequestStatus* status = &iStatus; |
|
232 User::RequestComplete(status, KErrNone); |
|
233 } |
|
234 |
|
235 // ----------------------------------------------------------------------------- |
|
236 // Stops the state machine |
|
237 // ----------------------------------------------------------------------------- |
|
238 // |
|
239 void CStateMachine::Stop() |
|
240 { |
|
241 LOG( "+ CStateMachine::Stop()" ); |
|
242 Cancel(); |
|
243 iDepTree->RemoveDownloadedFiles( FsSession() ); |
|
244 // Log statistics. Prevent divide-by-zero. |
|
245 if (iDownloadTime == 0) |
|
246 iDownloadTime = 1; |
|
247 LOG4( "Total %d kB in %.1f s, avg %.2f kB/s", |
|
248 iCumulativeDownloaded/1024, |
|
249 iDownloadTime/1000000.0, |
|
250 iCumulativeDownloaded*1000000.0 / iDownloadTime / 1024.0); |
|
251 } |
|
252 |
|
253 // ----------------------------------------------------------------------------- |
|
254 // Returns current state ID |
|
255 // ----------------------------------------------------------------------------- |
|
256 // |
|
257 TInt CStateMachine::StateIndex() const |
|
258 { |
|
259 return iStateFactory->StateIndex(iState); |
|
260 } |
|
261 |
|
262 // ----------------------------------------------------------------------------- |
|
263 // Request the next state we want the application to go to |
|
264 // ----------------------------------------------------------------------------- |
|
265 // |
|
266 void CStateMachine::SetState(const CStateFactory::TAppState aState) |
|
267 { |
|
268 SetState( iStateFactory->GetState(aState) ); |
|
269 } |
|
270 |
|
271 // ----------------------------------------------------------------------------- |
|
272 // Set the starting state of the state machine, but do not invoke state change |
|
273 // ----------------------------------------------------------------------------- |
|
274 // |
|
275 void CStateMachine::SetStartState(const CStateFactory::TAppState aState) |
|
276 { |
|
277 iState = &iStateFactory->GetState( aState ); |
|
278 } |
|
279 |
|
280 // ----------------------------------------------------------------------------- |
|
281 // Request the next state we want the application to go to |
|
282 // ----------------------------------------------------------------------------- |
|
283 // |
|
284 void CStateMachine::SetState(TState& aState) |
|
285 { |
|
286 LOG3( "+ SetState(): %d -> %d", iStateFactory->StateIndex(iState), iStateFactory->StateIndex(&aState) ); |
|
287 |
|
288 iState->Exit(); |
|
289 iState = &aState; |
|
290 SetActive(); |
|
291 // send signal that this request has completed |
|
292 TRequestStatus* status = &iStatus; |
|
293 User::RequestComplete(status, KErrNone); |
|
294 |
|
295 //LOG2( "- SetState(): now in %d", iStateFactory->StateIndex(iState) ); |
|
296 } |
|
297 |
|
298 // ----------------------------------------------------------------------------- |
|
299 // Active object heart |
|
300 // ----------------------------------------------------------------------------- |
|
301 // |
|
302 void CStateMachine::RunL() |
|
303 { |
|
304 //LOG2( "+ CStateEngine::RunL(): state=%d", iStateFactory->StateIndex(iState) ); |
|
305 iState->Enter(); |
|
306 //LOG2( "- CStateEngine::RunL(): %d", iStateFactory->StateIndex(iState) ); |
|
307 } |
|
308 |
|
309 // ----------------------------------------------------------------------------- |
|
310 // Handles the leaves from RunL(). |
|
311 // |
|
312 // SPECIFIC CASES NOT DONE YET: |
|
313 // - |
|
314 // ----------------------------------------------------------------------------- |
|
315 // |
|
316 TInt CStateMachine::RunError(const TInt aError) |
|
317 { |
|
318 LOG3("+ SM::RunError(): %d, %d", StateIndex(), aError ); |
|
319 |
|
320 TExitReason err = EInstallationFailed; |
|
321 |
|
322 switch ( aError ) |
|
323 { |
|
324 case KLeaveExit: |
|
325 { |
|
326 // TODO: Ugly hack: we need to return KLeaveExit as RunError() |
|
327 // gets called when application exit is called within RunL(). |
|
328 //LOG( "Exit() left" ); |
|
329 return KLeaveExit; |
|
330 } |
|
331 case SwiUI::KSWInstErrUserCancel: |
|
332 { |
|
333 LOG( "User cancelled installation" ); |
|
334 // User cancelled the installation |
|
335 err = EUserCancelled; |
|
336 } |
|
337 break; |
|
338 case SwiUI::KSWInstErrInsufficientMemory: |
|
339 { |
|
340 LOG( "Installer left: not enough space" ); |
|
341 err = EInsufficientMemory; |
|
342 } |
|
343 break; |
|
344 case SwiUI::KSWInstErrMissingDependency: |
|
345 { |
|
346 LOG( "Installer left: missing dependency." ); |
|
347 //err = EInstallationFailed; |
|
348 } |
|
349 break; |
|
350 case SwiUI::KSWInstErrFileCorrupted: |
|
351 case SwiUI::KSWInstErrPackageNotSupported: |
|
352 case SwiUI::KSWInstErrGeneralError: |
|
353 case SwiUI::KSWInstErrNoRights: |
|
354 case SwiUI::KSWInstErrNetworkFailure: |
|
355 case SwiUI::KSWInstErrAccessDenied: |
|
356 case SwiUI::KSWInstUpgradeError: |
|
357 { |
|
358 LOG2( "Installer left, err=%d", aError ); |
|
359 //err = EInstallationFailed; |
|
360 } |
|
361 break; |
|
362 case KErrServerTerminated: |
|
363 { |
|
364 LOG( "Server process terminated, cannot continue." ); |
|
365 } |
|
366 break; |
|
367 case EUnsupportedDevice: |
|
368 { |
|
369 LOG( "MachineId not present in supported devices list" ); |
|
370 err = EDeviceNotSupported; |
|
371 } |
|
372 break; |
|
373 case KErrAlreadyExists: |
|
374 { |
|
375 // Download already exists |
|
376 LOG( "Existing download" ); |
|
377 err = EDownloadFailed; |
|
378 } |
|
379 break; |
|
380 default: |
|
381 { |
|
382 LOG2( "Uncategorized leave %d, exiting", aError ); |
|
383 } |
|
384 break; |
|
385 } |
|
386 |
|
387 LOG2( "Exiting due to failure %d", err ); |
|
388 SetFailureReason( err ); |
|
389 SetState( CStateFactory::EStatePrepareExitWithError ); |
|
390 |
|
391 return KErrNone; |
|
392 } |
|
393 |
|
394 // ----------------------------------------------------------------------------- |
|
395 // |
|
396 // ----------------------------------------------------------------------------- |
|
397 // |
|
398 void CStateMachine::DoCancel() |
|
399 { |
|
400 LOG( "CStateMachine::DoCancel()" ); |
|
401 iDownloadHandler->CancelAllDownloads(); |
|
402 iInstallManager->CancelAll(); |
|
403 } |
|
404 |
|
405 // ----------------------------------------------------------------------------- |
|
406 // Sets the internet access point identifier for download handler |
|
407 // ----------------------------------------------------------------------------- |
|
408 // |
|
409 void CStateMachine::SetIAP(TUint32 aIAP) |
|
410 { |
|
411 iDownloadHandler->SetIAP(aIAP); |
|
412 } |
|
413 |
|
414 // ----------------------------------------------------------------------------- |
|
415 // Handles the UI event from AppUi, filters it and passes it to states. |
|
416 // ----------------------------------------------------------------------------- |
|
417 // |
|
418 void CStateMachine::HandleUserResponse(TInt aStatus) |
|
419 { |
|
420 switch (aStatus) |
|
421 { |
|
422 case EAknSoftkeyYes: |
|
423 iState->UserAccepted(); |
|
424 break; |
|
425 case EAknSoftkeyNo: |
|
426 iState->UserRejected(); |
|
427 break; |
|
428 case EAknSoftkeyCancel: |
|
429 case EKeyPhoneEnd: |
|
430 // fall-through |
|
431 default: |
|
432 iState->UserCancelled(); |
|
433 break; |
|
434 } |
|
435 } |
|
436 |
|
437 // ----------------------------------------------------------------------------- |
|
438 // |
|
439 // ----------------------------------------------------------------------------- |
|
440 // |
|
441 void CStateMachine::HandleInstallCompletedL(TInt aStatus) |
|
442 { |
|
443 LOG4( "HandleInstallCompletedL(%d): %d. '%S'", aStatus, StateIndex(), iCurrentPackage->GetSisPackageName() ); |
|
444 // TODO: Can iCurrentPackage ever be null? In case of root package installation?? |
|
445 |
|
446 iState->InstallCompleted( aStatus ); |
|
447 } |
|
448 |
|
449 // ----------------------------------------------------------------------------- |
|
450 // Called, if IAP has changed |
|
451 // ----------------------------------------------------------------------------- |
|
452 // |
|
453 void CStateMachine::HandleIapChanged(const TUint32 aIAP) |
|
454 { |
|
455 iAppUi.iIAP = aIAP; |
|
456 SetIAP(aIAP); |
|
457 } |
|
458 |
|
459 // ----------------------------------------------------------------------------- |
|
460 // Called when download has finished. |
|
461 // ----------------------------------------------------------------------------- |
|
462 // |
|
463 void CStateMachine::HandleHttpFetchCompleted( |
|
464 const TDesC& aDlFilename, |
|
465 const TInt /* aDownloadType */, |
|
466 const TInt32 aBytesDownloaded, |
|
467 const TReal32 aAvgDlSpeed, // bytes/second |
|
468 const TInt64 aDlTime // microseconds |
|
469 ) |
|
470 { |
|
471 delete iDownloadedFile; |
|
472 iDownloadedFile = NULL; |
|
473 iDownloadedFile = aDlFilename.Alloc(); |
|
474 iDownloadSize = aBytesDownloaded; |
|
475 // Indicate that we've downloaded this amount already to keep progress bar happy |
|
476 iCumulativeDownloaded += aBytesDownloaded; |
|
477 // Calculate cumulative average download speed |
|
478 iDownloadTime += aDlTime; |
|
479 |
|
480 #ifdef DEBUG_ADM |
|
481 TReal32 avgDlSpeed = iCumulativeDownloaded*1000000.0 / iDownloadTime; |
|
482 |
|
483 #ifdef _DEBUG |
|
484 TBuf<32> buf; |
|
485 TReal r = avgDlSpeed; |
|
486 TRealFormat fmt(3, 2); |
|
487 fmt.iType = KRealFormatFixed; // | KDoNotUseTriads; |
|
488 buf.AppendNum(r/1024.0, fmt); |
|
489 buf.Append(' '); |
|
490 buf.Append(iAppUi.iPrefixKb); |
|
491 buf.Append('/'); |
|
492 buf.Append('s'); |
|
493 iAppUi.EikonEnv()->InfoMsg(buf); |
|
494 #endif |
|
495 |
|
496 LOG8( "DL %7d/%7d (%.1f s, %3.02f kB/s) (total: %d kB, %.1f s, avg %.02f kB/s) OK", |
|
497 aBytesDownloaded, aBytesDownloaded, aDlTime/1000000.0, aAvgDlSpeed/1024.0, |
|
498 iCumulativeDownloaded/1024, iDownloadTime/1000000.0, avgDlSpeed/1024.0 ); |
|
499 #endif |
|
500 iState->DownloadCompleted(aBytesDownloaded); |
|
501 } |
|
502 |
|
503 // ----------------------------------------------------------------------------- |
|
504 // Called when download manager has retrieved a packet from the network. |
|
505 // Required for updating the progress bar. |
|
506 // ----------------------------------------------------------------------------- |
|
507 // |
|
508 void CStateMachine::HandleHttpFetchInProgress(const TInt32 aAlreadyDownloaded, const TInt32 aDownloadSize, const TReal32 aAvgDlSpeed) |
|
509 { |
|
510 iState->DownloadInProgress(aAlreadyDownloaded, aDownloadSize, aAvgDlSpeed); |
|
511 } |
|
512 |
|
513 // ----------------------------------------------------------------------------- |
|
514 // Called when download manager encounters a problem while downloading |
|
515 // ----------------------------------------------------------------------------- |
|
516 // |
|
517 void CStateMachine::HandleHttpFetchFailure( |
|
518 const TDesC& aDlFilename, |
|
519 const TInt aGlobalErrorId, |
|
520 const TInt aErrorId, |
|
521 const TInt aFetchType |
|
522 ) |
|
523 { |
|
524 if (aFetchType) |
|
525 { |
|
526 LOG5( "+ HandleHttpFetchFailure(): %d. %d, %d '%S'", StateIndex(), aGlobalErrorId, aErrorId, &aDlFilename ); |
|
527 } |
|
528 delete iDownloadedFile; |
|
529 iDownloadedFile = NULL; |
|
530 iDownloadedFile = aDlFilename.Alloc(); |
|
531 // TODO: Filter the errors here and invoke proper callbacks in states |
|
532 iState->DownloadFailed(); |
|
533 LOG( "- HandleHttpFetchFailure()" ); |
|
534 } |
|
535 |
|
536 // ----------------------------------------------------------------------------- |
|
537 // Signals the semaphore that download deleting is in progress (and the installation |
|
538 // can safely continue). |
|
539 // ----------------------------------------------------------------------------- |
|
540 // |
|
541 void CStateMachine::HandleDownloadDeleting() |
|
542 { |
|
543 iDlDeletingSemaphore.Signal(); |
|
544 } |
|
545 |
|
546 // ============================================================================= |
|
547 |
|
548 // ----------------------------------------------------------------------------- |
|
549 // |
|
550 // ----------------------------------------------------------------------------- |
|
551 // |
|
552 TState& CStateFactory::GetState(const TAppState aState) const |
|
553 { |
|
554 __ASSERT_DEBUG( aState < EStateLast, Panic(EPanicStateIndexOutOfBounds) ); |
|
555 return *iStates[aState]; |
|
556 } |
|
557 |
|
558 // ----------------------------------------------------------------------------- |
|
559 // |
|
560 // ----------------------------------------------------------------------------- |
|
561 // |
|
562 TInt CStateFactory::StateIndex(const TState* aState) const |
|
563 { |
|
564 TInt state; |
|
565 for (state = 0; state < EStateLast; state++) |
|
566 { |
|
567 if (iStates[state] == aState) |
|
568 { |
|
569 return state; |
|
570 } |
|
571 } |
|
572 // We end up here, if the state is not set, which may happen, if this |
|
573 // is called before CStateMachine::Start() or CStateMachine::SetState(). |
|
574 return KUnknownState; |
|
575 } |
|
576 |
|
577 // ----------------------------------------------------------------------------- |
|
578 // Creates a new CStateFactory. |
|
579 // @return Newly created CStateFactory. |
|
580 // ----------------------------------------------------------------------------- |
|
581 // |
|
582 CStateFactory* CStateFactory::NewL(CStateMachine& aStateMachine) |
|
583 { |
|
584 CStateFactory* self = new (ELeave) CStateFactory(aStateMachine); |
|
585 CleanupStack::PushL(self); |
|
586 |
|
587 // Create the states |
|
588 self->iStates[EStateSetup] = new (ELeave) TStateSetup(*self); |
|
589 self->iStates[EStateSetupParsing] = new (ELeave) TStateSetupParsing(*self); |
|
590 self->iStates[EStateBuildDepTree] = new (ELeave) TStateBuildDepTree(*self); |
|
591 self->iStates[EStateDownloadDepFile] = new (ELeave) TStateDownloadDepFile(*self); |
|
592 self->iStates[EStateParseDepFile] = new (ELeave) TStateParseDepFile(*self); |
|
593 self->iStates[EStateDownloadChangesFile] = new (ELeave) TStateDownloadChangesFile(*self); |
|
594 self->iStates[EStateParseChangesFile] = new (ELeave) TStateParseChangesFile(*self); |
|
595 self->iStates[EStateBuildFetchList] = new (ELeave) TStateBuildFetchList(*self); |
|
596 self->iStates[EStateVerifyAvailableDiskSpace] = new (ELeave) TStateVerifyAvailableDiskSpace(*self); |
|
597 self->iStates[EStateConfirmDownload] = new (ELeave) TStateConfirmDownload(*self); |
|
598 self->iStates[EStateConfirmRoamingDownload] = new (ELeave) TStateConfirmRoamingDownload(*self); |
|
599 self->iStates[EStateStartDependencyDownload] = new (ELeave) TStateStartDependencyDownload(*self); |
|
600 self->iStates[EStateDownloadDependency] = new (ELeave) TStateDownloadDependency(*self); |
|
601 self->iStates[EStateInstallDependency] = new (ELeave) TStateInstallDependency(*self); |
|
602 self->iStates[EStateInstallAppSis] = new (ELeave) TStateInstallAppSis(*self); |
|
603 self->iStates[EStateUninstallDependency] = new (ELeave) TStateUninstallDependency(*self); |
|
604 self->iStates[EStatePrepareExitWithError] = new (ELeave) TStatePrepareExitWithError(*self); |
|
605 self->iStates[EStateLaunchApp] = new (ELeave) TStateLaunchApp(*self); |
|
606 self->iStates[EStateExit] = new (ELeave) TStateExit(*self); |
|
607 |
|
608 CleanupStack::Pop(); |
|
609 |
|
610 return self; |
|
611 } |
|
612 |
|
613 // ----------------------------------------------------------------------------- |
|
614 // Default constructor |
|
615 // ----------------------------------------------------------------------------- |
|
616 // |
|
617 CStateFactory::CStateFactory(CStateMachine& aStateMachine) : |
|
618 iStateMachine(aStateMachine) |
|
619 { |
|
620 } |
|
621 |
|
622 // ----------------------------------------------------------------------------- |
|
623 // Default destructor |
|
624 // ----------------------------------------------------------------------------- |
|
625 // |
|
626 CStateFactory::~CStateFactory() |
|
627 { |
|
628 // Deletes all state objects |
|
629 iStates.DeleteAll(); |
|
630 } |
|
631 |
|
632 // ============================================================================= |
|
633 |
|
634 TState::TState(const CStateFactory& aFactory) : |
|
635 iFactory(aFactory), |
|
636 iStateMachine(aFactory.StateMachine()) |
|
637 { |
|
638 } |
|
639 |
|
640 void TState::PanicInState(TStatePanic aPanic) const |
|
641 { |
|
642 Panic(aPanic, iFactory.StateIndex(this)); |
|
643 } |
|
644 |
|
645 // Change of states |
|
646 void TState::Enter() const |
|
647 { |
|
648 } |
|
649 |
|
650 void TState::Exit() const |
|
651 { |
|
652 } |
|
653 |
|
654 // Events from UI |
|
655 void TState::UserAccepted() |
|
656 { |
|
657 LOG_FUNC |
|
658 } |
|
659 |
|
660 // ----------------------------------------------------------------------------- |
|
661 // Implements the default user cancel behaviour. If needed, overwrite in the |
|
662 // state implementation. |
|
663 // ----------------------------------------------------------------------------- |
|
664 // |
|
665 void TState::UserCancelled() |
|
666 { |
|
667 LOG_FUNC |
|
668 iStateMachine.SetFailureReason(EUserCancelled); |
|
669 iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError ); |
|
670 } |
|
671 |
|
672 // ----------------------------------------------------------------------------- |
|
673 // Implements the default user reject behaviour. If needed, overwrite in the |
|
674 // state implementation. |
|
675 // ----------------------------------------------------------------------------- |
|
676 // |
|
677 void TState::UserRejected() |
|
678 { |
|
679 UserCancelled(); |
|
680 } |
|
681 |
|
682 // Events from DownloadManager |
|
683 void TState::DownloadInProgress(const TInt /* aAlreadyDownloaded */, const TInt /* aDownloadSize */, const TReal32 /* aAvgDlSpeed */) |
|
684 { |
|
685 //LOG_FUNC |
|
686 } |
|
687 |
|
688 void TState::DownloadCompleted(const TInt /* aBytesDownloaded */) |
|
689 { |
|
690 LOG_FUNC |
|
691 } |
|
692 |
|
693 void TState::DownloadFailed() |
|
694 { |
|
695 LOG_FUNC |
|
696 } |
|
697 |
|
698 void TState::DownloadFailed(const CStateFactory::TAppState aState) |
|
699 { |
|
700 const EDownloadError errId = iStateMachine.iDownloadHandler->GetDownloadError(); |
|
701 SLOG3( "+ DownloadFailed(): %d. err=%d", iStateMachine.StateIndex(), errId ); |
|
702 |
|
703 if ( (errId == EDlErrDownloadFailure ) && ( iStateMachine.iRestartAttempt < KDownloadRestartRetries) ) |
|
704 { |
|
705 iStateMachine.iRestartAttempt++; |
|
706 SLOG2( "Download restart, attempt %d", iStateMachine.iRestartAttempt ); |
|
707 iStateMachine.SetState( aState ); |
|
708 } |
|
709 else |
|
710 { |
|
711 SLOG3( "Aborting download. (%d; %d)", iStateMachine.iRestartAttempt, errId ); |
|
712 // iStateMachine.iRestartAttempt = 0; |
|
713 iStateMachine.SetFailureReason(EDownloadFailed); |
|
714 iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError ); |
|
715 } |
|
716 } |
|
717 |
|
718 void TState::DownloadCancelled() |
|
719 { |
|
720 LOG_FUNC |
|
721 iStateMachine.SetFailureReason(EUserCancelled); |
|
722 iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError ); |
|
723 } |
|
724 |
|
725 // Events from InstallManager |
|
726 void TState::InstallInProgress() |
|
727 { |
|
728 LOG_FUNC |
|
729 } |
|
730 |
|
731 void TState::InstallCompleted(TInt /* aStatus */) |
|
732 { |
|
733 LOG_FUNC |
|
734 } |
|
735 |
|
736 void TState::InstallationCancelled() |
|
737 { |
|
738 LOG_FUNC |
|
739 } |
|
740 |
|
741 // ============================================================================= |
|
742 TStateSetup::TStateSetup(const CStateFactory& aFactory) : |
|
743 TState(aFactory) |
|
744 { |
|
745 LOG_FUNC |
|
746 } |
|
747 |
|
748 void TStateSetup::Enter() const |
|
749 { |
|
750 LOG_FUNC |
|
751 |
|
752 // TODO: Check if we are roaming and proceed according to that |
|
753 |
|
754 iStateMachine.SetState( CStateFactory::EStateSetupParsing ); |
|
755 } |
|
756 |
|
757 TStateSetupParsing::TStateSetupParsing(const CStateFactory& aFactory) : |
|
758 TState(aFactory) |
|
759 { |
|
760 } |
|
761 |
|
762 void TStateSetupParsing::Enter() const |
|
763 { |
|
764 const TInt mUid = iStateMachine.MachineUid(); |
|
765 if ( mUid ) |
|
766 { |
|
767 iStateMachine.iDepTree->SetMachineId( mUid ); |
|
768 } |
|
769 else |
|
770 { |
|
771 PanicInState( EPanicStateInvalidMachineUid ); |
|
772 } |
|
773 |
|
774 // Get the drive where wrapper package was installed to |
|
775 const TBool driveStatus = iStateMachine.iInstallManager->GetPackageInstalledDriveL( |
|
776 iStateMachine.WrapperPackageUid(), |
|
777 iStateMachine.iWrapperInstalledDrive); |
|
778 |
|
779 |
|
780 #ifdef __WINS__ |
|
781 iStateMachine.iWrapperInstalledDrive = 'C'; |
|
782 #else |
|
783 if ( !driveStatus ) |
|
784 { |
|
785 // Read the wrapper installed drive from resume info file. |
|
786 // TODO: What if user has tried to install on a removable drive and it's not available during the menu launch? |
|
787 } |
|
788 #endif |
|
789 |
|
790 SLOG3( "Installer pkg on %c: (%d)", (char)iStateMachine.iWrapperInstalledDrive, driveStatus ); |
|
791 |
|
792 // Cannot combine this with drive status. User might be trying to reinstall an app, already present in the device! |
|
793 TVersion version, minVersion = KMinBootstrapSisVersion; |
|
794 if ( iStateMachine.iInstallManager->GetPackageVersionInfoL(KUidBootstrap, version) ) |
|
795 { |
|
796 // Compare installed and min required Bootstrap versions |
|
797 if ( CompareVersions(minVersion, version) == EGreaterFirstVersion ) |
|
798 { |
|
799 iStateMachine.SetFailureReason( EInvalidBootstrapVersion ); |
|
800 iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError ); |
|
801 return; |
|
802 } |
|
803 } |
|
804 else |
|
805 { |
|
806 // Launched from the menu grid |
|
807 } |
|
808 |
|
809 switch ( iStateMachine.BootstrapVersion() ) |
|
810 { |
|
811 case 1: |
|
812 case 2: |
|
813 case 3: |
|
814 { |
|
815 // Parses the dependency file included withing the wrapper package. |
|
816 SLOG2( "* Parsing '%S'", iStateMachine.DepFilename() ); |
|
817 iStateMachine.iXmlParser->GetDepContentsL( |
|
818 *iStateMachine.DepFilename(), |
|
819 iStateMachine.iCurrentPackage, |
|
820 iStateMachine.iDepTree |
|
821 ); |
|
822 iStateMachine.SetState( CStateFactory::EStateBuildDepTree ); |
|
823 } |
|
824 break; |
|
825 case 4: |
|
826 { |
|
827 // Parses the application.sis file included in the wrapper package. |
|
828 SLOG2( "* Parsing '%S'", iStateMachine.SisFilename() ); |
|
829 iStateMachine.iSisParser->GetDepContentsL( |
|
830 *iStateMachine.SisFilename(), |
|
831 iStateMachine.iCurrentPackage, |
|
832 iStateMachine.iDepTree |
|
833 ); |
|
834 iStateMachine.SetState( CStateFactory::EStateBuildDepTree ); |
|
835 } |
|
836 break; |
|
837 default: |
|
838 { |
|
839 SLOG2( "Invalid bootstrap v%d", iStateMachine.BootstrapVersion() ); |
|
840 iStateMachine.SetFailureReason( EInvalidBootstrapVersion ); |
|
841 iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError ); |
|
842 } |
|
843 break; |
|
844 } |
|
845 } |
|
846 |
|
847 // ----------------------------------------------------------------------------- |
|
848 // |
|
849 // ----------------------------------------------------------------------------- |
|
850 // |
|
851 TStateParseDepFile::TStateParseDepFile(const CStateFactory& aFactory) : |
|
852 TState(aFactory) |
|
853 { |
|
854 } |
|
855 |
|
856 void TStateParseDepFile::Enter() const |
|
857 { |
|
858 SLOG2( "+ ParseDepFileL(): '%S'", iStateMachine.iDownloadedFile ); |
|
859 iStateMachine.iXmlParser->GetDepContentsL( |
|
860 *iStateMachine.iDownloadedFile, |
|
861 iStateMachine.iCurrentPackage, |
|
862 iStateMachine.iDepTree |
|
863 ); |
|
864 iStateMachine.SetState( CStateFactory::EStateBuildDepTree ); |
|
865 SLOG2( "- ParseDepFileL(): '%S'", iStateMachine.iDownloadedFile ); |
|
866 } |
|
867 |
|
868 // ----------------------------------------------------------------------------- |
|
869 // |
|
870 // ----------------------------------------------------------------------------- |
|
871 // |
|
872 TStateParseChangesFile::TStateParseChangesFile(const CStateFactory& aFactory) : |
|
873 TState(aFactory) |
|
874 { |
|
875 } |
|
876 |
|
877 void TStateParseChangesFile::Enter() const |
|
878 { |
|
879 SLOG2("+ ParseChangesFileL(): '%S'", iStateMachine.iDownloadedFile); |
|
880 // Parse the provided changes file. |
|
881 // the parameter aChangesFileName will be invalid after the call |
|
882 iStateMachine.iXmlParser->GetChangesInfoL( |
|
883 *iStateMachine.iDownloadedFile, |
|
884 iStateMachine.iCurrentPackage, |
|
885 iStateMachine.iDepTree |
|
886 ); |
|
887 iStateMachine.SetState( CStateFactory::EStateDownloadDepFile ); |
|
888 SLOG2( "- ParseChangesFileL(): '%S'", iStateMachine.iDownloadedFile ); |
|
889 } |
|
890 |
|
891 // ----------------------------------------------------------------------------- |
|
892 // |
|
893 // ----------------------------------------------------------------------------- |
|
894 // |
|
895 TStateBuildFetchList::TStateBuildFetchList(const CStateFactory& aFactory) : |
|
896 TState(aFactory) |
|
897 { |
|
898 } |
|
899 |
|
900 void TStateBuildFetchList::Enter() const |
|
901 { |
|
902 // Construct the list of dependent packages |
|
903 SLOG( "Building dependency list" ); |
|
904 iStateMachine.iDepTree->ConstructFetchListL(); |
|
905 |
|
906 // Remove all downloaded dep files |
|
907 SLOG( "Removing downloaded files" ); |
|
908 iStateMachine.iDepTree->RemoveDownloadedFiles( iStateMachine.FsSession() ); |
|
909 |
|
910 // Check if cycle exists |
|
911 if ( iStateMachine.iDepTree->IsCyclePresent() ) |
|
912 { |
|
913 // TODO: Inform user about configuration failure, exit gracefully |
|
914 SLOG( "! Failure: cycle exists in the graph." ); |
|
915 iStateMachine.SetFailureReason( EInstallationFailed ); |
|
916 iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError ); |
|
917 } |
|
918 iStateMachine.SetState( CStateFactory::EStateVerifyAvailableDiskSpace ); |
|
919 } |
|
920 |
|
921 // ----------------------------------------------------------------------------- |
|
922 // |
|
923 // ----------------------------------------------------------------------------- |
|
924 // |
|
925 TStateVerifyAvailableDiskSpace::TStateVerifyAvailableDiskSpace(const CStateFactory& aFactory) : |
|
926 TState(aFactory) |
|
927 { |
|
928 } |
|
929 |
|
930 void TStateVerifyAvailableDiskSpace::Enter() const |
|
931 { |
|
932 // MaxDownloadSize is subtracted from available System drive space. |
|
933 |
|
934 // In case of silent installation of main app, if there is no space available in the drive selected by the user for wrapper, |
|
935 // normal installation to follow. |
|
936 |
|
937 // Set the drive info |
|
938 if ( iStateMachine.iDepTree->SetDriveInfo() ) |
|
939 { |
|
940 // With Ovi Store prompt always |
|
941 const TInt dlThreshold = iStateMachine.OviStoreRunning() |
|
942 ? 0 |
|
943 : KDownloadPromptThreshold; |
|
944 const TInt dlSize = iStateMachine.iDepTree->GetTotalDownloadSize(); |
|
945 |
|
946 SLOG3( "Download size %d (%d)", dlSize, dlThreshold ); |
|
947 |
|
948 #ifdef DEBUG_ADM |
|
949 // Print all the drives set. To be removed after testing. |
|
950 CPackageInfo *node = NULL; |
|
951 while( (node = iStateMachine.iDepTree->GetNextSortedNode()) != NULL ) |
|
952 { |
|
953 SLOG5( "PkgUid 0x%08X: InstDrive %c:, prio %d, size %d", |
|
954 node->GetPackageUid(), (char)node->GetInstallDrive(), |
|
955 node->GetDrivePriority(), node->GetInstallSize() ); |
|
956 } |
|
957 #endif |
|
958 // Show user how much to download and confirm, if he/she wants to do that |
|
959 // if we have dependencies to download at all |
|
960 if ( dlSize > 0 ) |
|
961 { |
|
962 // Finalize the progress bar |
|
963 iStateMachine.UpdateProgressBar( KProgressBarFullValue, KProgressBarFullValue ); |
|
964 |
|
965 // We need to download dependencies |
|
966 if ( iStateMachine.UsingWLAN() && !iStateMachine.OviStoreRunning() ) |
|
967 { |
|
968 // If using WLAN, start the dependency download immediately without prompting the user |
|
969 iStateMachine.SetState( CStateFactory::EStateStartDependencyDownload ); |
|
970 } |
|
971 else if ( iStateMachine.RegisteredRoaming() ) |
|
972 { |
|
973 // If the device is roaming, always prompt the user |
|
974 iStateMachine.SetState( CStateFactory::EStateConfirmRoamingDownload ); |
|
975 } |
|
976 else if ( dlSize > dlThreshold ) |
|
977 { |
|
978 // If not using WLAN and the download threshold has exceeded, prompt the user |
|
979 iStateMachine.SetState( CStateFactory::EStateConfirmDownload ); |
|
980 } |
|
981 else |
|
982 { |
|
983 // Otherwise, continue the download automatically without prompting the user |
|
984 iStateMachine.SetState( CStateFactory::EStateStartDependencyDownload ); |
|
985 } |
|
986 } |
|
987 else |
|
988 { |
|
989 SLOG( "Nothing to download, dependencies OK." ); |
|
990 // Keep the next progress bar update happy |
|
991 iStateMachine.iProgressMaxValue = KProgressBarFullValue; |
|
992 // Finalize the progress bar |
|
993 iStateMachine.UpdateProgressBar( KProgressBarFullValue*95/100, KProgressBarFullValue ); |
|
994 iStateMachine.SetState( CStateFactory::EStateInstallAppSis ); |
|
995 } |
|
996 } |
|
997 else |
|
998 { |
|
999 iStateMachine.SetFailureReason( EInsufficientMemory ); |
|
1000 iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError ); |
|
1001 } |
|
1002 } |
|
1003 |
|
1004 // ----------------------------------------------------------------------------- |
|
1005 // Builds the dependency tree. This function controls the state machine. |
|
1006 // ----------------------------------------------------------------------------- |
|
1007 // |
|
1008 TStateBuildDepTree::TStateBuildDepTree(const CStateFactory& aFactory) : |
|
1009 TState(aFactory) |
|
1010 { |
|
1011 } |
|
1012 |
|
1013 void TStateBuildDepTree::Enter() const |
|
1014 { |
|
1015 SLOG2( "+ BuildDepTreeL(%d)", iStateMachine.iNodesProcessed ); |
|
1016 |
|
1017 // Update progress bar |
|
1018 iStateMachine.iNodesProcessed++; |
|
1019 |
|
1020 iStateMachine.iCurrentPackage = iStateMachine.iDepTree->GetNextNode(); |
|
1021 CPackageInfo* package = iStateMachine.iCurrentPackage; |
|
1022 |
|
1023 if ( package == NULL ) |
|
1024 { |
|
1025 SLOG( "Last package processed" ); |
|
1026 // Do the final progress bar update |
|
1027 iStateMachine.UpdateProgressBar( KProgressBarFullValue*95/100, KProgressBarFullValue ); |
|
1028 |
|
1029 iStateMachine.SetState( CStateFactory::EStateBuildFetchList ); |
|
1030 } |
|
1031 else |
|
1032 { |
|
1033 SLOG3( "* Processing 0x%08X (%d)", package->GetPackageUid(), package->GetPackageStatus() ); |
|
1034 |
|
1035 iStateMachine.UpdateProgressBar( iStateMachine.iNodesProcessed, |
|
1036 iStateMachine.iNodesProcessed+2 ); |
|
1037 |
|
1038 // Call the install class api to validate and set the package status |
|
1039 TUid uid = TUid::Uid( package->GetPackageUid() ); |
|
1040 TVersion version, test; |
|
1041 |
|
1042 test = package->GetPackageVersion(); |
|
1043 |
|
1044 if (iStateMachine.iInstallManager->GetPackageVersionInfoL(uid, version)) |
|
1045 { |
|
1046 // Compare installed and required verions |
|
1047 // to find if upgrade is required. |
|
1048 if ( (CompareVersions(test, version) ) == EGreaterFirstVersion) |
|
1049 { |
|
1050 SLOG8( "Package 0x%08X: upgrade %d.%02d.%d -> %d.%02d.%d", |
|
1051 uid.iUid, |
|
1052 version.iMajor, version.iMinor, version.iBuild, |
|
1053 test.iMajor, test.iMinor, test.iBuild |
|
1054 ); |
|
1055 package->SetPackageStatus(EPackageToBeUpgraded); |
|
1056 } |
|
1057 else |
|
1058 { |
|
1059 SLOG5( "Package 0x%08X: v%d.%02d.%d already installed", uid.iUid, |
|
1060 version.iMajor, version.iMinor, version.iBuild |
|
1061 ); |
|
1062 package->SetPackageStatus(EPackageInstalled); |
|
1063 } |
|
1064 } |
|
1065 else |
|
1066 { |
|
1067 SLOG5( "Package 0x%08X: v%d.%02d.%d to be downloaded", uid.iUid, |
|
1068 test.iMajor, test.iMinor, test.iBuild |
|
1069 ); |
|
1070 package->SetPackageStatus(EPackageToBeFetched); |
|
1071 } |
|
1072 |
|
1073 iStateMachine.SetState( CStateFactory::EStateDownloadChangesFile ); |
|
1074 } |
|
1075 SLOG2( "- BuildDepTreeL(%d)", iStateMachine.iNodesProcessed ); |
|
1076 } |
|
1077 |
|
1078 // ----------------------------------------------------------------------------- |
|
1079 // Requests a download for the dependecy sis package _dep.xml file. |
|
1080 // ----------------------------------------------------------------------------- |
|
1081 // |
|
1082 TStateDownloadDepFile::TStateDownloadDepFile(const CStateFactory& aFactory) : |
|
1083 TState(aFactory) |
|
1084 { |
|
1085 } |
|
1086 |
|
1087 void TStateDownloadDepFile::Enter() const |
|
1088 { |
|
1089 //Here fetch the dep file of the current package. |
|
1090 SLOG2( "+ FetchDepFileL(): 0x%08X", iStateMachine.iCurrentPackage->GetPackageUid() ); |
|
1091 |
|
1092 // TODO:Here the download Url should never be null] |
|
1093 // as its mandatory to specify the Url in changes file. |
|
1094 TPtrC8 urlPtr(NULL, 0); |
|
1095 if (iStateMachine.iCurrentPackage->GetDownloadUrlL() != NULL) |
|
1096 { |
|
1097 SLOG8_2( "DepPkg URL: '%S'", iStateMachine.iCurrentPackage->GetDownloadUrlL() ); |
|
1098 urlPtr.Set(iStateMachine.iCurrentPackage->GetDownloadUrlL()->Des() ); |
|
1099 } |
|
1100 else |
|
1101 { |
|
1102 SLOG8_2( "DepPkg URL: '%S' (default)", iStateMachine.ConfigUrl() ); |
|
1103 urlPtr.Set( *iStateMachine.ConfigUrl() ); |
|
1104 } |
|
1105 |
|
1106 User::LeaveIfNull( iStateMachine.iCurrentPackage->GetDepFileName() ); |
|
1107 |
|
1108 SLOG2( "Downloading DEP: '%S'", iStateMachine.iCurrentPackage->GetDepFileName() ); |
|
1109 |
|
1110 iStateMachine.iDownloadHandler->StartDownloadL( |
|
1111 urlPtr, |
|
1112 *iStateMachine.iCurrentPackage->GetDepFileName(), |
|
1113 iStateMachine.iDepTree->GetDownloadPath(), |
|
1114 1); |
|
1115 // We don't request a new state after this. When download completes |
|
1116 // succesfully, a new state change will be requested. |
|
1117 } |
|
1118 |
|
1119 void TStateDownloadDepFile::DownloadCompleted(const TInt /* aBytesDownloaded */) |
|
1120 { |
|
1121 iStateMachine.iRestartAttempt = 0; |
|
1122 iStateMachine.SetState( CStateFactory::EStateParseDepFile ); |
|
1123 } |
|
1124 |
|
1125 void TStateDownloadDepFile::DownloadFailed() |
|
1126 { |
|
1127 LOG_FUNC |
|
1128 TState::DownloadFailed( CStateFactory::EStateDownloadDepFile ); |
|
1129 } |
|
1130 |
|
1131 // ----------------------------------------------------------------------------- |
|
1132 // Requests a download for the _changes.xml file. |
|
1133 // ----------------------------------------------------------------------------- |
|
1134 // |
|
1135 TStateDownloadChangesFile::TStateDownloadChangesFile(const CStateFactory& aFactory) : |
|
1136 TState(aFactory) |
|
1137 { |
|
1138 } |
|
1139 |
|
1140 void TStateDownloadChangesFile::Enter() const |
|
1141 { |
|
1142 // See if the URL is provided as part of the |
|
1143 // dep file, otherwise use the default one. |
|
1144 TPtrC8 urlPtr(NULL, 0); |
|
1145 if ( iStateMachine.iCurrentPackage->GetURL() != NULL ) |
|
1146 { |
|
1147 SLOG8_2( "Changes URL: '%S'", iStateMachine.iCurrentPackage->GetURL() ); |
|
1148 urlPtr.Set(iStateMachine.iCurrentPackage->GetURL()->Des()); |
|
1149 } |
|
1150 else |
|
1151 { |
|
1152 SLOG8_2( "Changes URL: '%S' (default)", iStateMachine.ConfigUrl() ); |
|
1153 urlPtr.Set( *iStateMachine.ConfigUrl() ); |
|
1154 } |
|
1155 |
|
1156 //TODO: The only reason why this is back here : |
|
1157 //Changes file name for Root is not set when root is parsed. Fix it. |
|
1158 iStateMachine.iCurrentPackage->SetChangesFileNameL(); |
|
1159 SLOG2( "Downloading CHANGES: '%S'", iStateMachine.iCurrentPackage->GetChangesFileName() ); |
|
1160 |
|
1161 // Download the changes file |
|
1162 iStateMachine.iDownloadHandler->StartDownloadL( |
|
1163 urlPtr, |
|
1164 *iStateMachine.iCurrentPackage->GetChangesFileName(), |
|
1165 iStateMachine.iDepTree->GetDownloadPath(), |
|
1166 0); |
|
1167 // We don't request a new state after this. When download completes |
|
1168 // succesfully, a new state change will be requested by DownloadCompleted() |
|
1169 } |
|
1170 |
|
1171 void TStateDownloadChangesFile::DownloadCompleted(const TInt /*aBytesDownloaded*/) |
|
1172 { |
|
1173 LOG_FUNC |
|
1174 |
|
1175 iStateMachine.iNodesProcessed++; |
|
1176 iStateMachine.UpdateProgressBar( iStateMachine.iNodesProcessed, iStateMachine.iNodesProcessed+2 ); |
|
1177 |
|
1178 iStateMachine.iRestartAttempt = 0; |
|
1179 iStateMachine.SetState( CStateFactory::EStateParseChangesFile ); |
|
1180 } |
|
1181 |
|
1182 void TStateDownloadChangesFile::DownloadFailed() |
|
1183 { |
|
1184 LOG_FUNC |
|
1185 TState::DownloadFailed( CStateFactory::EStateDownloadChangesFile ); |
|
1186 } |
|
1187 |
|
1188 // ----------------------------------------------------------------------------- |
|
1189 // |
|
1190 // ----------------------------------------------------------------------------- |
|
1191 // |
|
1192 TStateStartDependencyDownload::TStateStartDependencyDownload(const CStateFactory& aFactory) : |
|
1193 TState(aFactory) |
|
1194 { |
|
1195 } |
|
1196 |
|
1197 void TStateStartDependencyDownload::Enter() const |
|
1198 { |
|
1199 const TUint32 totalDlSize = iStateMachine.iDepTree->GetTotalDownloadSize(); |
|
1200 SLOG2( "Starting to download %d bytes", totalDlSize ); |
|
1201 |
|
1202 // Remove all downloads before proceeding |
|
1203 iStateMachine.iDownloadHandler->CancelAllDownloads(); |
|
1204 |
|
1205 // Start progress bar from beginning |
|
1206 iStateMachine.iCounterCurrent = 1; |
|
1207 iStateMachine.iCounterMax = iStateMachine.iDepTree->CountDownloadNodes(); |
|
1208 |
|
1209 // reset to zero for download and install of packages. |
|
1210 iStateMachine.iDownloadSize = 0; |
|
1211 iStateMachine.iNodesProcessed = 0; |
|
1212 |
|
1213 // Start the dependency download! |
|
1214 iStateMachine.SetState( CStateFactory::EStateDownloadDependency ); |
|
1215 } |
|
1216 |
|
1217 // ----------------------------------------------------------------------------- |
|
1218 // |
|
1219 // ----------------------------------------------------------------------------- |
|
1220 // |
|
1221 TStateDownloadDependency::TStateDownloadDependency(const CStateFactory& aFactory) : |
|
1222 TState(aFactory), |
|
1223 iRetryDownload(EFalse) |
|
1224 { |
|
1225 } |
|
1226 |
|
1227 void TStateDownloadDependency::Enter() const |
|
1228 { |
|
1229 SLOG3( "+ FetchPackageL(%d): retry=%d", iStateMachine.iNodesProcessed, iRetryDownload ); |
|
1230 |
|
1231 CPackageInfo* fetchPackage = NULL; |
|
1232 |
|
1233 if ( iRetryDownload ) |
|
1234 { |
|
1235 fetchPackage = iStateMachine.iDepTree->GetCurrentFetchNode(); |
|
1236 } |
|
1237 else |
|
1238 { |
|
1239 iStateMachine.iNodesProcessed++; |
|
1240 // always ensure that iCurrentPackage points to the correct one |
|
1241 fetchPackage = iStateMachine.iDepTree->GetNextFetchNode(); |
|
1242 } |
|
1243 iStateMachine.iCurrentPackage = fetchPackage; |
|
1244 |
|
1245 if ( !fetchPackage ) |
|
1246 { |
|
1247 /* |
|
1248 //end of list - we're finished |
|
1249 SLOG2( "Uninstalling wrapper 0x%08X", iStateMachine.WrapperPackageUid().iUid ); |
|
1250 TInt err = iStateMachine.iInstallManager->SilentUnInstallPackage( |
|
1251 iStateMachine.WrapperPackageUid() ); |
|
1252 SLOG2( "Uninstall status: %d", err); |
|
1253 */ |
|
1254 // Wrapper has been uninstalled, ready to exit/launch |
|
1255 iStateMachine.SetState( CStateFactory::EStateExit ); |
|
1256 return; |
|
1257 } |
|
1258 /* |
|
1259 // Attempting to fix 'Network connection lost!' errors on 3G. Does not help. |
|
1260 SLOG( "Deleting all downloads" ); |
|
1261 iStateMachine.iDownloadHandler->CancelAllDownloads(); |
|
1262 */ |
|
1263 switch ( fetchPackage->GetPackageStatus() ) |
|
1264 { |
|
1265 case EPackageRootToBeInstalled: |
|
1266 { |
|
1267 //SLOG( "* Installing AppSis" ); |
|
1268 |
|
1269 iStateMachine.SetState( CStateFactory::EStateInstallAppSis ); |
|
1270 } |
|
1271 break; |
|
1272 case EPackageToBeFetched: |
|
1273 case EPackageToBeUpgraded: |
|
1274 { |
|
1275 SLOG2( "* Package 0x%08X to be Fetched/Upgraded", fetchPackage->GetPackageUid() ); |
|
1276 |
|
1277 // Initialize progress bar |
|
1278 //ShowGlobalProgressL(R_ADM_DOWNLOAD_WAIT_TEXT, 0, KMaxTInt); |
|
1279 |
|
1280 if ( iStateMachine.iCounterMax > 0 ) |
|
1281 { |
|
1282 iStateMachine.StopWaitNote(); |
|
1283 // prevent progress bar from starting from previous dl size |
|
1284 iStateMachine.iProgressCurrentValue = 0; |
|
1285 iStateMachine.iCumulativeDepDownloaded = 0; |
|
1286 iStateMachine.iProgressMaxValue = fetchPackage->GetDownloadSize(); |
|
1287 iStateMachine.ShowProgressBarL( |
|
1288 0, |
|
1289 iStateMachine.iProgressMaxValue, |
|
1290 iStateMachine.iCounterCurrent, |
|
1291 iStateMachine.iCounterMax |
|
1292 ); |
|
1293 } |
|
1294 |
|
1295 // TODO:Here the download Url should never be null, |
|
1296 // as its mandatory to specify the Url in changes file. |
|
1297 TPtrC8 urlPtr(NULL, 0); |
|
1298 if (fetchPackage->GetDownloadUrlL() != NULL ) |
|
1299 { |
|
1300 SLOG8_2( "Package URL: '%S'", fetchPackage->GetDownloadUrlL()); |
|
1301 urlPtr.Set(fetchPackage->GetDownloadUrlL()->Des()); |
|
1302 } |
|
1303 else |
|
1304 { |
|
1305 SLOG8_2( "Package URL: '%S' (default)", iStateMachine.ConfigUrl() ); |
|
1306 urlPtr.Set(*iStateMachine.ConfigUrl()); |
|
1307 } |
|
1308 |
|
1309 User::LeaveIfNull( fetchPackage->GetSisPackageName() ); |
|
1310 |
|
1311 SLOG2( "Downloading: '%S'", fetchPackage->GetSisPackageName() ); |
|
1312 iStateMachine.iDownloadHandler->StartDownloadL( |
|
1313 urlPtr, |
|
1314 *fetchPackage->GetSisPackageName(), |
|
1315 iStateMachine.iDepTree->GetDownloadPath(), |
|
1316 2); |
|
1317 } |
|
1318 break; |
|
1319 case EPackageInstalled: |
|
1320 { |
|
1321 SLOG2( "* Package 0x%08X installed", fetchPackage->GetPackageUid()); |
|
1322 //FetchPackageL(); |
|
1323 iStateMachine.SetState( CStateFactory::EStateDownloadDependency ); |
|
1324 } |
|
1325 break; |
|
1326 default: |
|
1327 { |
|
1328 // TODO: Better error handling |
|
1329 Panic( EPanicStateFetchStatus ); |
|
1330 } |
|
1331 break; |
|
1332 } // switch |
|
1333 SLOG2( "- FetchPackageL(%d)", iStateMachine.iNodesProcessed ); |
|
1334 } |
|
1335 |
|
1336 void TStateDownloadDependency::DownloadCompleted(const TInt aBytesDownloaded) |
|
1337 { |
|
1338 iRetryDownload = EFalse; |
|
1339 // Indicate that we've downloaded this amount already to keep progress bar happy |
|
1340 iStateMachine.iCumulativeDepDownloaded += aBytesDownloaded; |
|
1341 iStateMachine.iDownloadSize = iStateMachine.iCumulativeDepDownloaded; |
|
1342 iStateMachine.SetState( CStateFactory::EStateInstallDependency ); |
|
1343 } |
|
1344 |
|
1345 void TStateDownloadDependency::DownloadInProgress(const TInt aAlreadyDownloaded, const TInt aDownloadSize, const TReal32 aAvgDlSpeed) |
|
1346 { |
|
1347 static TInt32 prevAlready = 0; |
|
1348 // Prevents log and event flooding |
|
1349 if (aAlreadyDownloaded != prevAlready) |
|
1350 { |
|
1351 prevAlready = aAlreadyDownloaded; |
|
1352 |
|
1353 iStateMachine.iDownloadSize = aAlreadyDownloaded + iStateMachine.iCumulativeDepDownloaded; |
|
1354 iStateMachine.iProgressCurrentValue = |
|
1355 iStateMachine.iCumulativeDepDownloaded + aAlreadyDownloaded; |
|
1356 if (aAvgDlSpeed > 0) |
|
1357 { |
|
1358 SLOG4( "DL %7d/%7d (%3.02f kB/s)", aAlreadyDownloaded, aDownloadSize, aAvgDlSpeed/1024 ); |
|
1359 } |
|
1360 else |
|
1361 { |
|
1362 SLOG3( "DL %7d/%7d", aAlreadyDownloaded, aDownloadSize ); |
|
1363 } |
|
1364 // Update the progress bar |
|
1365 iStateMachine.UpdateProgressBar( iStateMachine.iProgressCurrentValue, |
|
1366 iStateMachine.iProgressMaxValue ); |
|
1367 } |
|
1368 } |
|
1369 |
|
1370 void TStateDownloadDependency::DownloadFailed() |
|
1371 { |
|
1372 LOG_FUNC |
|
1373 iRetryDownload = ETrue; |
|
1374 TState::DownloadFailed( CStateFactory::EStateDownloadDependency ); |
|
1375 } |
|
1376 |
|
1377 // ----------------------------------------------------------------------------- |
|
1378 // Uninstalls installed dependencies one at the time |
|
1379 // ----------------------------------------------------------------------------- |
|
1380 // |
|
1381 TStateUninstallDependency::TStateUninstallDependency(const CStateFactory& aFactory) : |
|
1382 TState(aFactory) |
|
1383 { |
|
1384 } |
|
1385 |
|
1386 void TStateUninstallDependency::Enter() const |
|
1387 { |
|
1388 CPackageInfo* node = iStateMachine.iDepTree->GetPreviousFetchNode(); |
|
1389 // Uninstall all the fetched and installed dependencies |
|
1390 if (node) |
|
1391 { |
|
1392 // TODO: Can the package present check be moved to Install handler?. Below is an async function though. |
|
1393 if ( (node->GetPackageStatus() == EPackageFetchedInstalled) && |
|
1394 ( iStateMachine.iInstallManager->IsPackagePresentL(TUid::Uid(node->GetPackageUid())) ) ) |
|
1395 { |
|
1396 SLOG2( "Uninstalling: 0x%x", node->GetPackageUid() ); |
|
1397 |
|
1398 iStateMachine.iInstallManager-> |
|
1399 SilentUninstallPackageAsync( TUid::Uid(node->GetPackageUid()) ); |
|
1400 // the next event will be triggered by InstallCompleted() below |
|
1401 } |
|
1402 else |
|
1403 { |
|
1404 SLOG2( "Skipping: 0x%x", node->GetPackageUid() ); |
|
1405 // Process the next package |
|
1406 iStateMachine.SetState( CStateFactory::EStateUninstallDependency ); |
|
1407 } |
|
1408 } |
|
1409 else |
|
1410 { |
|
1411 SLOG( "About to uninstall wrapper" ); |
|
1412 // We've processed the dependency tree, uninstall the wrapper |
|
1413 // Failure reason is set before calling EPrepareForExitWithError |
|
1414 iStateMachine.SetState( CStateFactory::EStateExit ); |
|
1415 } |
|
1416 } |
|
1417 |
|
1418 // This is actually handling the UNinstallation completed event |
|
1419 void TStateUninstallDependency::InstallCompleted(TInt aStatus) |
|
1420 { |
|
1421 SLOG2( "UninstallDependencyCompleted(): %d", aStatus ); |
|
1422 // Try to uninstall next dependency, without minding the status code |
|
1423 iStateMachine.SetState( CStateFactory::EStateUninstallDependency ); |
|
1424 } |
|
1425 |
|
1426 // ----------------------------------------------------------------------------- |
|
1427 // |
|
1428 // ----------------------------------------------------------------------------- |
|
1429 // |
|
1430 TStateLaunchApp::TStateLaunchApp(const CStateFactory& aFactory) : |
|
1431 TState(aFactory) |
|
1432 { |
|
1433 } |
|
1434 |
|
1435 void TStateLaunchApp::Enter() const |
|
1436 { |
|
1437 RArray<TUid> appSids; |
|
1438 TBool launchStatus = ETrue; |
|
1439 // Get the SID list from installer |
|
1440 TUid uid = TUid::Uid( iStateMachine.iCurrentPackage->GetPackageUid() ); |
|
1441 const TBool status = iStateMachine.iInstallManager->GetPackageSidsL(uid, appSids); |
|
1442 |
|
1443 if ( status ) |
|
1444 { |
|
1445 #ifdef DEBUG_ADM |
|
1446 for (TInt i = 0; i < appSids.Count(); i++) |
|
1447 { |
|
1448 SLOG3( "SID[%d]=0x%08X", i, appSids[i] ); |
|
1449 } |
|
1450 #endif |
|
1451 TApaAppInfo appInfo; |
|
1452 RApaLsSession lsSession; |
|
1453 |
|
1454 // Connect to Apparc |
|
1455 if ( !lsSession.Connect() ) |
|
1456 { |
|
1457 CleanupClosePushL( lsSession ); |
|
1458 |
|
1459 for (TInt i = 0; i < appSids.Count(); i++) |
|
1460 { |
|
1461 TInt ret = lsSession.GetAppInfo( appInfo, appSids[i] ); |
|
1462 // Get the app Info of the Sid. |
|
1463 if ( ret == KErrNone ) |
|
1464 { |
|
1465 HBufC* iconFilename = NULL; |
|
1466 // Get the application icon, if any. It's used in the launch dialog. |
|
1467 ret = lsSession.GetAppIcon( appSids[i], iconFilename ); |
|
1468 if (ret == KErrNone) |
|
1469 { |
|
1470 // We have a launchable exe and icon: get the executable name and caption |
|
1471 iStateMachine.iLaunchName = appInfo.iFullName; |
|
1472 iStateMachine.iLaunchCaption = appInfo.iCaption; |
|
1473 iStateMachine.iLaunchIconFilename.Copy( *iconFilename ); |
|
1474 SLOG5( "LaunchExe %d '%S' '%S' '%S'", i, &iStateMachine.iLaunchName, &iStateMachine.iLaunchCaption, &iStateMachine.iLaunchIconFilename ); |
|
1475 |
|
1476 delete iconFilename; |
|
1477 break; |
|
1478 } |
|
1479 // The .exe didn't have an icon, try next .exe. |
|
1480 // We're assuming that only exe's having an icon are the ones we should launch |
|
1481 } // if |
|
1482 } // for |
|
1483 CleanupStack::PopAndDestroy( &lsSession ); |
|
1484 } //if ( !lsSession.Connect() ) |
|
1485 else |
|
1486 { |
|
1487 launchStatus = EFalse; |
|
1488 } |
|
1489 } // if( status ) |
|
1490 else |
|
1491 { |
|
1492 launchStatus = EFalse; |
|
1493 } |
|
1494 |
|
1495 appSids.Close(); |
|
1496 |
|
1497 if ( launchStatus && iStateMachine.iLaunchName.Length() ) |
|
1498 { |
|
1499 iStateMachine.SetAppLaunch(ETrue); |
|
1500 iStateMachine.iAppUi.ShowLaunchPromptL( iStateMachine.iLaunchCaption, iStateMachine.iLaunchIconFilename ); |
|
1501 } |
|
1502 else |
|
1503 { |
|
1504 // No executable to launch! |
|
1505 iStateMachine.SetState( CStateFactory::EStateExit ); |
|
1506 } |
|
1507 } |
|
1508 |
|
1509 // ----------------------------------------------------------------------------- |
|
1510 // |
|
1511 // ----------------------------------------------------------------------------- |
|
1512 // |
|
1513 void TStateLaunchApp::UserAccepted() |
|
1514 { |
|
1515 RApaLsSession lsSession; |
|
1516 |
|
1517 // Connect to Apparc |
|
1518 User::LeaveIfError( lsSession.Connect() ); |
|
1519 CleanupClosePushL( lsSession ); |
|
1520 |
|
1521 CApaCommandLine* cmdLine = CApaCommandLine::NewLC(); |
|
1522 cmdLine->SetExecutableNameL( iStateMachine.iLaunchName ); |
|
1523 cmdLine->SetCommandL( EApaCommandRun ); |
|
1524 |
|
1525 SLOG3( "Launching %S '%S'", &iStateMachine.iLaunchCaption, &iStateMachine.iLaunchName ); |
|
1526 // Launch the application |
|
1527 // TODO: Better error handling |
|
1528 User::LeaveIfError( lsSession.StartApp( *cmdLine ) ); |
|
1529 |
|
1530 CleanupStack::PopAndDestroy( 2, &lsSession ); // cmdLine, lsSession |
|
1531 |
|
1532 iStateMachine.SetState( CStateFactory::EStateExit ); |
|
1533 } |
|
1534 |
|
1535 // ----------------------------------------------------------------------------- |
|
1536 // |
|
1537 // ----------------------------------------------------------------------------- |
|
1538 // |
|
1539 void TStateLaunchApp::UserRejected() |
|
1540 { |
|
1541 SLOG( "User denied application launch" ); |
|
1542 iStateMachine.SetAppLaunch(EFalse); |
|
1543 iStateMachine.SetState( CStateFactory::EStateExit ); |
|
1544 } |
|
1545 |
|
1546 // ----------------------------------------------------------------------------- |
|
1547 // |
|
1548 // ----------------------------------------------------------------------------- |
|
1549 // |
|
1550 TStateExit::TStateExit(const CStateFactory& aFactory) : |
|
1551 TState(aFactory) |
|
1552 { |
|
1553 } |
|
1554 |
|
1555 void TStateExit::Enter() const |
|
1556 { |
|
1557 SLOG2( "Exit (%d)", iStateMachine.FailedState() ); |
|
1558 |
|
1559 #ifdef FEATURE_INSTALL_RESUME |
|
1560 // FailedState is checked to differentiate a completion of successful menu launch from failure cases. |
|
1561 // Also uninstall the wrapper, when the resume information file is not required |
|
1562 // (in case of Bootstrap failure mode - KCmdLineCancelAdmNoResume) |
|
1563 if ( ( iStateMachine.FailedState() == CStateFactory::EStateLast ) || |
|
1564 ( iStateMachine.FailedState() == KUnknownState ) || |
|
1565 ( !iStateMachine.ResumeRequired() ) |
|
1566 ) |
|
1567 { |
|
1568 // Do the final cleanup here: remove the wrapper package, which |
|
1569 // will also remove the bootstrap |
|
1570 SLOG2( "Uninstalling wrapper 0x%08X", iStateMachine.WrapperPackageUid().iUid ); |
|
1571 const TInt err = iStateMachine.iInstallManager->SilentUnInstallPackage( |
|
1572 iStateMachine.WrapperPackageUid() ); |
|
1573 if (err != KErrNone) |
|
1574 { |
|
1575 SLOG2( "! Uninstall failed (%d)", err ); |
|
1576 } |
|
1577 |
|
1578 // Remove resume info files |
|
1579 RemoveResumeFiles(); |
|
1580 } |
|
1581 else |
|
1582 { |
|
1583 // Remove only the bootstrap. |
|
1584 // Wrapper is retained for Menu launch. |
|
1585 // It is possible that bootstrap is already removed in previous unsuccessful menu launch |
|
1586 if ( iStateMachine.iInstallManager->IsPackagePresentL( KUidBootstrap ) ) |
|
1587 { |
|
1588 SLOG2( "Uninstalling bootstrap 0x%08X", KUidBootstrap ); |
|
1589 const TInt err = iStateMachine.iInstallManager->SilentUnInstallPackage( KUidBootstrap ); |
|
1590 // ignore any errors |
|
1591 if (err != KErrNone) |
|
1592 { |
|
1593 SLOG2( "! Uninstall failed (%d)", err ); |
|
1594 } |
|
1595 } |
|
1596 } |
|
1597 #else |
|
1598 // Do the final cleanup here: remove the wrapper package |
|
1599 SLOG2( "Uninstalling wrapper 0x%08X", iStateMachine.WrapperPackageUid().iUid ); |
|
1600 const TInt err = iStateMachine.iInstallManager->SilentUnInstallPackage( |
|
1601 iStateMachine.WrapperPackageUid() ); |
|
1602 if (err != KErrNone) |
|
1603 { |
|
1604 SLOG2( "! Uninstall failed (%d)", err ); |
|
1605 } |
|
1606 #endif // FEATURE_INSTALL_RESUME |
|
1607 |
|
1608 #ifdef FEATURE_REPORTING |
|
1609 // Report only the specified cases |
|
1610 switch ( iStateMachine.ExitReason() ) |
|
1611 { |
|
1612 case EExitNoError: |
|
1613 case EUserCancelled: |
|
1614 // case EDownloadFailed: |
|
1615 case EInsufficientMemory: |
|
1616 case EDeviceNotSupported: |
|
1617 case EInstallationFailed: |
|
1618 case EInvalidBootstrapVersion: |
|
1619 case ERootInstallationFailed: |
|
1620 Report(); |
|
1621 break; |
|
1622 default: |
|
1623 break; |
|
1624 } |
|
1625 #else |
|
1626 // We can exit the application |
|
1627 // The default failure reason is "No Error" |
|
1628 iStateMachine.iAppUi.ExitApp(); |
|
1629 |
|
1630 // Above call does not return |
|
1631 #endif |
|
1632 } |
|
1633 |
|
1634 // ----------------------------------------------------------------------------- |
|
1635 // RemoveResumeFiles() |
|
1636 // On successful completion of the installation process, remove the resume info file. |
|
1637 // ----------------------------------------------------------------------------- |
|
1638 // |
|
1639 void TStateExit::RemoveResumeFiles() const |
|
1640 { |
|
1641 if ( BaflUtils::FileExists(iStateMachine.FsSession(), KADMResumeInfoFile) ) |
|
1642 { |
|
1643 RArray< TPtrC > lineBuffer; |
|
1644 TInt ret = 0; |
|
1645 HBufC* buffer = ReadConfigFile( iStateMachine.FsSession(), KADMResumeInfoFile, lineBuffer, ret ); |
|
1646 |
|
1647 if ( buffer && ret == KErrNone ) |
|
1648 { |
|
1649 // Get AppFileName from the config file |
|
1650 TPtrC appFileNameLine = GetConfigValue( KRFieldAppFileName, lineBuffer, ret ); |
|
1651 if ( ret == KErrNone ) |
|
1652 { |
|
1653 SLOG2( "AppFileName = '%S'", &appFileNameLine ); |
|
1654 |
|
1655 if ( BaflUtils::FileExists(iStateMachine.FsSession(), appFileNameLine) ) |
|
1656 { |
|
1657 const TInt err = iStateMachine.FsSession().Delete( appFileNameLine ); |
|
1658 SLOG2( "AppFile has been deleted (%d)", err); |
|
1659 } |
|
1660 } |
|
1661 else |
|
1662 { |
|
1663 SLOG2( "Failed to read value from resume info (%d)", ret ); |
|
1664 } |
|
1665 delete buffer; |
|
1666 } |
|
1667 ret = iStateMachine.FsSession().Delete( KADMResumeInfoFile ); |
|
1668 SLOG2( "Resume info has been deleted (%d)", ret ); |
|
1669 |
|
1670 // TODO: Need to remove the copied dep file as well |
|
1671 } |
|
1672 } |
|
1673 #ifdef FEATURE_REPORTING |
|
1674 // ----------------------------------------------------------------------------- |
|
1675 // Creates a report about the installation and sends that to the server |
|
1676 // ----------------------------------------------------------------------------- |
|
1677 // |
|
1678 void TStateExit::Report() const |
|
1679 { |
|
1680 _LIT8(KFmtVersion, "%d.%02d.%d"); |
|
1681 _LIT(KOK, "OK"); |
|
1682 TBuf8<KMaxFileName> url; |
|
1683 url.Copy( *iStateMachine.ConfigUrl() ); |
|
1684 |
|
1685 // ----------------------------------------------------------------------------- |
|
1686 // The base report URL is: |
|
1687 // http://server/root/x.yy.z/reason/flags/OK |
|
1688 // |
|
1689 // where |
|
1690 // |
|
1691 // http://server/root/ ConfigUrl() |
|
1692 // x.yy.z ADM version formatted as %d.%02d.%d |
|
1693 // reason iExitReason |
|
1694 // flags Flags defined below in Report Version 1 |
|
1695 // OK Non-existing file |
|
1696 // |
|
1697 // ----------------------------------------------------------------------------- |
|
1698 // Report Version 1 |
|
1699 // |
|
1700 //31 11 10 9 8 7 6 5 4 3 2 1 0 |
|
1701 // +-------+--+--+--+--+--+--+--+--+--+--+--+--+ |
|
1702 // |reservd| | | | | |
|
1703 // +-------+--+--+--+--+--+--+--+--+--+--+--+--+ |
|
1704 // |
|
1705 // value |
|
1706 // bits range description |
|
1707 // 0-3 0-15 Report version |
|
1708 // |
|
1709 // Other bits for version 1 |
|
1710 // |
|
1711 // value |
|
1712 // bits range description |
|
1713 // 4-9 0-63 Number of packages downloaded |
|
1714 // 10 1 Ovi Store running |
|
1715 // 11 1 Application launched |
|
1716 // ----------------------------------------------------------------------------- |
|
1717 // |
|
1718 |
|
1719 // Get the ADM version |
|
1720 TVersion version; |
|
1721 iStateMachine.iInstallManager->GetPackageVersionInfoL(KUidADMApp, version); |
|
1722 |
|
1723 #if 0 |
|
1724 const TUint32 KReportVersion = 1; |
|
1725 TUint32 flags; |
|
1726 flags = KReportVersion << 0; // 4 bits (0-15) |
|
1727 flags |= (iStateMachine.iDepTree->CountDownloadNodes() & 0x3f) << 4; // 6 bits (0-63) |
|
1728 flags |= iStateMachine.OviStoreRunning() << 10; // 1 bit |
|
1729 flags |= iStateMachine.AppLaunch() << 11; // 1 bit |
|
1730 SLOG2( "Exit: 0x%08x", flags ); |
|
1731 #endif |
|
1732 |
|
1733 url.AppendFormat(KFmtVersion, version.iMajor, version.iMinor, version.iBuild); |
|
1734 url.Append('/'); |
|
1735 url.AppendNum( iStateMachine.ExitReason() ); |
|
1736 url.Append('/'); |
|
1737 url.AppendNum( iStateMachine.OviStoreRunning() ); |
|
1738 url.Append('/'); |
|
1739 url.AppendNum( iStateMachine.ResumingInstallation() ); |
|
1740 url.Append('/'); |
|
1741 #if 0 |
|
1742 url.AppendNumFixedWidthUC(flags, EHex, 8); |
|
1743 url.Append('/'); |
|
1744 url.AppendNum( iStateMachine.OviStoreRunning() ); |
|
1745 url.Append('/'); |
|
1746 url.AppendNum( iStateMachine.AppLaunch() ); |
|
1747 url.Append('/'); |
|
1748 #endif |
|
1749 iStateMachine.iDownloadHandler->StartDownloadL( |
|
1750 url, |
|
1751 KOK, |
|
1752 iStateMachine.iDepTree->GetDownloadPath(), |
|
1753 0); |
|
1754 } |
|
1755 |
|
1756 // ----------------------------------------------------------------------------- |
|
1757 // Ignore "in progress" event calls. |
|
1758 // ----------------------------------------------------------------------------- |
|
1759 // |
|
1760 void TStateExit::DownloadInProgress(const TInt /* aAlreadyDownloaded */, const TInt /* aDownloadSize */, const TReal32 /* aAvgDlSpeed */) |
|
1761 { |
|
1762 } |
|
1763 |
|
1764 // ----------------------------------------------------------------------------- |
|
1765 // Transfer control to ExitApp(). |
|
1766 // ----------------------------------------------------------------------------- |
|
1767 // |
|
1768 void TStateExit::DownloadCompleted(const TInt /* aBytesDownloaded */) |
|
1769 { |
|
1770 iStateMachine.iAppUi.ExitApp(); |
|
1771 } |
|
1772 |
|
1773 // ----------------------------------------------------------------------------- |
|
1774 // Transfer control to ExitApp(). |
|
1775 // ----------------------------------------------------------------------------- |
|
1776 // |
|
1777 void TStateExit::DownloadFailed() |
|
1778 { |
|
1779 iStateMachine.iAppUi.ExitApp(); |
|
1780 } |
|
1781 |
|
1782 // ----------------------------------------------------------------------------- |
|
1783 // Transfer control to ExitApp(). |
|
1784 // ----------------------------------------------------------------------------- |
|
1785 // |
|
1786 void TStateExit::DownloadCancelled() |
|
1787 { |
|
1788 iStateMachine.iAppUi.ExitApp(); |
|
1789 } |
|
1790 #endif |
|
1791 |
|
1792 // ----------------------------------------------------------------------------- |
|
1793 // |
|
1794 // ----------------------------------------------------------------------------- |
|
1795 // |
|
1796 TStatePrepareExitWithError::TStatePrepareExitWithError(const CStateFactory& aFactory) : |
|
1797 TState(aFactory) |
|
1798 { |
|
1799 } |
|
1800 |
|
1801 void TStatePrepareExitWithError::Enter() const |
|
1802 { |
|
1803 // Show the user a wait note, if needed |
|
1804 iStateMachine.iAppUi.HandleFailure(); |
|
1805 |
|
1806 // TODO: FIX THIS! DlMgr requires some time for its AOs to do the cleanup. |
|
1807 User::After(1000000); |
|
1808 iStateMachine.iDownloadHandler->CancelAllDownloads(); |
|
1809 iStateMachine.iDepTree->RemoveDownloadedFiles( iStateMachine.FsSession() ); |
|
1810 |
|
1811 #ifdef FEATURE_INSTALL_RESUME |
|
1812 // Backup the resume info for future launch |
|
1813 if ( iStateMachine.ResumeRequired() ) |
|
1814 { |
|
1815 // Create the resume information |
|
1816 if ( CreateInstallationResumeInfo() == KErrNone ) |
|
1817 { |
|
1818 // Dependencies are not uninstalled if launched from Menu |
|
1819 iStateMachine.SetState( CStateFactory::EStateExit ); |
|
1820 return; |
|
1821 } |
|
1822 } |
|
1823 // If no resume info required or CreateInstallationResumeInfo fails. |
|
1824 iStateMachine.SetState( CStateFactory::EStateUninstallDependency ); |
|
1825 #else |
|
1826 // Trigger the dependency uninstallation |
|
1827 iStateMachine.SetState( CStateFactory::EStateUninstallDependency ); |
|
1828 #endif // FEATURE_INSTALL_RESUME |
|
1829 } |
|
1830 |
|
1831 // ----------------------------------------------------------------------------- |
|
1832 // CreateInstallationResumeInfo |
|
1833 // Backup the necessary information to continue the installation later i.e. |
|
1834 // from the application menu grid. |
|
1835 // ----------------------------------------------------------------------------- |
|
1836 // |
|
1837 #define CHECK(a) { \ |
|
1838 if (a != KErrNone) \ |
|
1839 goto failed; \ |
|
1840 pos++; \ |
|
1841 } |
|
1842 |
|
1843 TInt TStatePrepareExitWithError::CreateInstallationResumeInfo() const |
|
1844 { |
|
1845 SLOG( "+ CreateInstallationResumeInfo()" ); |
|
1846 |
|
1847 // This is increment in each CHECK() macro |
|
1848 TInt pos = 0; |
|
1849 |
|
1850 // Step 0: Backup the required files to ADM Private folder. |
|
1851 // (Also the names are written to resume info file) |
|
1852 TRAPD( err, BackupFilesL() ); |
|
1853 CHECK(err); |
|
1854 |
|
1855 RFile outFile; |
|
1856 CPackageInfo* node = NULL; |
|
1857 |
|
1858 TInt numberOfNodes = iStateMachine.iDepTree->NodesCount(); |
|
1859 // Skip the main application |
|
1860 if (numberOfNodes > 0) |
|
1861 { |
|
1862 numberOfNodes--; |
|
1863 } |
|
1864 |
|
1865 err = outFile.Open( iStateMachine.FsSession(), KADMResumeInfoFile, EFileWrite | EFileStreamText | EFileShareAny ); |
|
1866 CHECK(err); |
|
1867 |
|
1868 // Step 1: Write the application name |
|
1869 node = iStateMachine.iDepTree->GetRootNode(); |
|
1870 SLOG3( "Saving state for '%S' (%d)", node->GetPackageName(), numberOfNodes ); |
|
1871 err = WriteToConfigFile( outFile, KRFieldAppName, *node->GetPackageName() ); |
|
1872 CHECK(err); |
|
1873 |
|
1874 // Step 2: Write the depPkg UIDs to resume info file. |
|
1875 // A new resume info file is already created as part of the "BackupFilesL()" |
|
1876 // If user presses cancel before the fetchlist is constructed, then this loop will not execute. |
|
1877 for (TInt i = 0; i < numberOfNodes; i++) |
|
1878 { |
|
1879 node = iStateMachine.iDepTree->GetFetchNode( i ); |
|
1880 SLOG2( "Adding info: 0x%08X", node->GetPackageUid() ); |
|
1881 |
|
1882 err = WriteIntToConfigFile( outFile, KRFieldDepPkgUid, node->GetPackageUid() ); |
|
1883 CHECK(err); |
|
1884 } |
|
1885 |
|
1886 #if 0 |
|
1887 node = iStateMachine.iDepTree->GetRootNode(); |
|
1888 SLOG2( "Adding main: 0x%08X", node->GetPackageUid() ); |
|
1889 |
|
1890 // Step 3: Write the Root pkg UID to resume info file. |
|
1891 // TODO: Check whether this is really needed. |
|
1892 err = WriteIntToConfigFile( outFile, KRootPkgUid, node->GetPackageUid() ); |
|
1893 CHECK(err); |
|
1894 #endif |
|
1895 |
|
1896 // Step 4: Write the BootstrapVersion to resume info file. |
|
1897 err = WriteIntToConfigFile( outFile, KRFieldBootstrap, iStateMachine.BootstrapVersion() ); |
|
1898 CHECK(err); |
|
1899 |
|
1900 // Step 5: Write the Wrapper installed drive to resume info file. |
|
1901 err = WriteIntToConfigFile( outFile, KRFieldWrapperDrive, iStateMachine.iWrapperInstalledDrive ); |
|
1902 CHECK(err); |
|
1903 |
|
1904 // Step 6: Write the Wrapper Package UID. |
|
1905 err = WriteIntToConfigFile( outFile, KRFieldWrapperPkgUid, iStateMachine.WrapperPackageUid().iUid ); |
|
1906 |
|
1907 if (err != KErrNone) |
|
1908 { |
|
1909 failed: |
|
1910 SLOG3( "Resume info creation failed (%d: %d)", pos, err ); |
|
1911 // Remove the resume info file in error situation as it might not contain |
|
1912 // all the information needed to continue the installation |
|
1913 const TInt deleteStatus = iStateMachine.FsSession().Delete(KADMResumeInfoFile); |
|
1914 SLOG2( "Resume info has been removed (%d)", deleteStatus ); |
|
1915 } |
|
1916 |
|
1917 if (pos) |
|
1918 { |
|
1919 outFile.Close(); |
|
1920 } |
|
1921 |
|
1922 SLOG2( "- CreateInstallationResumeInfo(): %d", err ); |
|
1923 |
|
1924 return err; |
|
1925 } |
|
1926 |
|
1927 // ----------------------------------------------------------------------------- |
|
1928 // BackupFiles |
|
1929 // In case of failure during the complete installation process, |
|
1930 // backup the required files for future launch. |
|
1931 // ----------------------------------------------------------------------------- |
|
1932 // |
|
1933 void TStatePrepareExitWithError::BackupFilesL() const |
|
1934 { |
|
1935 #if 0 |
|
1936 HBufC* destFileName = NULL; |
|
1937 TInt err = KErrNone, pos = 0; |
|
1938 |
|
1939 // Backup the main application sis file to a folder. - Copy to ADM Private folder?! |
|
1940 TParsePtrC appFileName( *iStateMachine.SisFilename() ); |
|
1941 |
|
1942 destFileName = HBufC::NewLC( appFileName.NameAndExt().Length() + KADMPrivatePath().Length() ); |
|
1943 TPtr nameBufPtr = destFileName->Des(); |
|
1944 |
|
1945 nameBufPtr.Append( KADMPrivatePath ); |
|
1946 nameBufPtr.Append( appFileName.NameAndExt() ); |
|
1947 |
|
1948 // TODO: Do the file copying in AO |
|
1949 CFileMan* fileMan = CFileMan::NewL( iStateMachine.FsSession() ); |
|
1950 CleanupStack::PushL(fileMan); |
|
1951 err = fileMan->Copy( *iStateMachine.SisFilename(), *destFileName ); |
|
1952 CleanupStack::PopAndDestroy(fileMan); |
|
1953 |
|
1954 if (err != KErrNone) |
|
1955 { |
|
1956 failed: |
|
1957 CleanupStack::PopAndDestroy(destFileName); |
|
1958 SLOG3( "Failed to create backup (%d: %d)", pos, err ); |
|
1959 User::Leave(err); |
|
1960 } |
|
1961 |
|
1962 // Backup the info. The file is not present yet. |
|
1963 RFile outFile; |
|
1964 err = outFile.Replace( iStateMachine.FsSession(), KADMResumeInfoFile, EFileWrite | EFileStreamText | EFileShareAny ); |
|
1965 CHECK(err); |
|
1966 |
|
1967 // TODO: Backup the depfile in case of Bootstrap version 2 and save the name as well. |
|
1968 |
|
1969 // Write the AppFilename to resume info file. |
|
1970 err = WriteToConfigFile( outFile, KAppFileName, destFileName->Des() ); |
|
1971 CHECK(err); |
|
1972 CleanupStack::PopAndDestroy(); // destFileName |
|
1973 #endif |
|
1974 // Backup the info. The file is not present yet. |
|
1975 RFile outFile; |
|
1976 |
|
1977 // If no resume info file exists, create a new one. |
|
1978 // In case a resume info file exists, replace the file with a new one. |
|
1979 // (One resume information file supported at any point of time) |
|
1980 TInt err = outFile.Replace( iStateMachine.FsSession(), KADMResumeInfoFile, EFileWrite | EFileStreamText | EFileShareAny ); |
|
1981 |
|
1982 if (err != KErrNone) |
|
1983 { |
|
1984 goto failed; |
|
1985 } |
|
1986 |
|
1987 // TODO: Backup the depfile in case of Bootstrap version 2 and save the name as well. |
|
1988 |
|
1989 // Write the AppFilename to resume info file. |
|
1990 err = WriteToConfigFile( outFile, KRFieldAppFileName, iStateMachine.SisFilename()->Des() ); |
|
1991 |
|
1992 if (err != KErrNone) |
|
1993 { |
|
1994 failed: |
|
1995 SLOG2( "- BackupFiles(): LEAVE %d", err ); |
|
1996 outFile.Close(); |
|
1997 User::Leave(err); |
|
1998 } |
|
1999 |
|
2000 outFile.Close(); |
|
2001 } |
|
2002 |
|
2003 // ----------------------------------------------------------------------------- |
|
2004 // |
|
2005 // ----------------------------------------------------------------------------- |
|
2006 // |
|
2007 TStateInstallDependency::TStateInstallDependency(const CStateFactory& aFactory) : |
|
2008 TState(aFactory) |
|
2009 { |
|
2010 } |
|
2011 |
|
2012 void TStateInstallDependency::Enter() const |
|
2013 { |
|
2014 SLOG3( "Installing '%S' to %c:", iStateMachine.iDownloadedFile, (char)iStateMachine.iCurrentPackage->GetInstallDrive() ); |
|
2015 // Replace the downloading note with installing note |
|
2016 iStateMachine.ShowInstallingWaitNoteL( iStateMachine.iCounterCurrent, iStateMachine.iCounterMax ); |
|
2017 iStateMachine.StopProgressBar(); |
|
2018 |
|
2019 // TODO: FIX THIS! This is an ugly hack to give time for S60 DlMgr AOs to |
|
2020 // finish their cleanups. To fix this properly, we need to wait till we get |
|
2021 // "EHttpDlDeleting" event before starting the installation. This has to be |
|
2022 // called before CancelAllDownloads(), otherwise DlMgrServer will die in |
|
2023 // CBase91 PANIC. |
|
2024 User::After(1000000); |
|
2025 // We need to remove the download(s) before starting the installation. |
|
2026 // Otherwise we might get KErrInUse error while installing. This happens |
|
2027 // quite often when using E: / F: drive as the download drive. |
|
2028 iStateMachine.iDownloadHandler->CancelAllDownloads(); |
|
2029 |
|
2030 // Wait for the "DlDeleting" event |
|
2031 iStateMachine.iDlDeletingSemaphore.Wait(KDlDeletingTimeout); |
|
2032 |
|
2033 iStateMachine.iInstallManager->SilentInstallPackageL( |
|
2034 *iStateMachine.iDownloadedFile, |
|
2035 iStateMachine.iCurrentPackage->GetInstallDrive() |
|
2036 ); |
|
2037 |
|
2038 iStateMachine.UpdateProgressBar(iStateMachine.iCumulativeDepDownloaded, |
|
2039 iStateMachine.iProgressMaxValue ); |
|
2040 } |
|
2041 |
|
2042 void TStateInstallDependency::Exit() const |
|
2043 { |
|
2044 // Remove the wait note |
|
2045 #if 0 |
|
2046 if ( !iStateMachine.OviStoreRunning() ) |
|
2047 { |
|
2048 iStateMachine.StopWaitNote(); |
|
2049 } |
|
2050 #endif |
|
2051 } |
|
2052 |
|
2053 void TStateInstallDependency::InstallCompleted(TInt aStatus) |
|
2054 { |
|
2055 LOG_FUNC |
|
2056 |
|
2057 CPackageInfo *curr = iStateMachine.iDepTree->GetCurrentFetchNode(); |
|
2058 User::LeaveIfNull(curr); |
|
2059 SLOG3( "Removing '%S%S'", &iStateMachine.iDepTree->GetDownloadPath(), curr->GetSisPackageName() ); |
|
2060 |
|
2061 // Delete the .sis file as its no longer required. |
|
2062 iStateMachine.iDepTree->DeleteFile( iStateMachine.FsSession(), |
|
2063 *curr->GetSisPackageName(), |
|
2064 iStateMachine.iDepTree->GetDownloadPath() |
|
2065 ); |
|
2066 if (aStatus == KErrNone) |
|
2067 { |
|
2068 if (curr->GetPackageStatus() == EPackageToBeFetched ) |
|
2069 { |
|
2070 curr->SetPackageStatus(EPackageFetchedInstalled); |
|
2071 } |
|
2072 else if (curr->GetPackageStatus() == EPackageRootToBeInstalled ) |
|
2073 { |
|
2074 curr->SetPackageStatus(EPackageRootInstalled); |
|
2075 } |
|
2076 else |
|
2077 { |
|
2078 SLOG2( "Unexpected package status %d", curr->GetPackageStatus() ); |
|
2079 } |
|
2080 |
|
2081 // Dependency package succesfully installed, update the counter to keep UI happy |
|
2082 iStateMachine.iCounterCurrent++; |
|
2083 // Download the next dependency |
|
2084 iStateMachine.SetState( CStateFactory::EStateDownloadDependency ); |
|
2085 } |
|
2086 else |
|
2087 { |
|
2088 SLOG2( "Dependency installation failed %d", aStatus ); |
|
2089 iStateMachine.SetFailureReason( EInstallationFailed ); |
|
2090 iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError ); |
|
2091 } |
|
2092 } |
|
2093 |
|
2094 // ----------------------------------------------------------------------------- |
|
2095 // |
|
2096 // ----------------------------------------------------------------------------- |
|
2097 // |
|
2098 TStateInstallAppSis::TStateInstallAppSis(const CStateFactory& aFactory) : |
|
2099 TState(aFactory) |
|
2100 { |
|
2101 } |
|
2102 |
|
2103 void TStateInstallAppSis::Enter() const |
|
2104 { |
|
2105 // We need to find the root package |
|
2106 if (iStateMachine.iCurrentPackage == NULL) |
|
2107 { |
|
2108 SLOG( "Finding root package" ); |
|
2109 CPackageInfo* package = NULL; |
|
2110 while ( (package = iStateMachine.iDepTree->GetNextFetchNode()) != NULL ) |
|
2111 { |
|
2112 if (package->GetPackageStatus() == EPackageRootToBeInstalled) |
|
2113 { |
|
2114 SLOG3( "Root: UID 0x%08X, '%S'", package->GetPackageUid(), package->GetPackageName() ); |
|
2115 break; |
|
2116 } |
|
2117 } |
|
2118 iStateMachine.iCurrentPackage = package; |
|
2119 } |
|
2120 // iStateMachine.iCurrentPackage should now point to a correct packege, |
|
2121 // the application.sis, in this case. Just make sure, it really does that. |
|
2122 // Do we have a package set? |
|
2123 if ( iStateMachine.iCurrentPackage ) |
|
2124 { |
|
2125 if ( iStateMachine.BootstrapVersion() == 3 ) |
|
2126 { |
|
2127 /* |
|
2128 SLOG( "Uninstalling smartinstaller (bootstrap)" ); |
|
2129 TInt err = iStateMachine.iInstallManager->SilentUnInstallPackage( |
|
2130 iStateMachine.WrapperPackageUid() ); |
|
2131 SLOG2( "Uninstall status: %d", err); |
|
2132 */ |
|
2133 // Delete the dependency file that was provided with the wrapper |
|
2134 // TODO: Remove if(), DeleteFile() copes with NULL filenames. |
|
2135 if ( iStateMachine.DepFilename() ) |
|
2136 { |
|
2137 iStateMachine.iAppUi.DeleteFile( *iStateMachine.DepFilename() ); |
|
2138 } |
|
2139 |
|
2140 #ifdef FEATURE_LAUNCH_INSTALLED_APP |
|
2141 SLOG( "Dependencies and application are installed, ready to launch!" ); |
|
2142 iStateMachine.SetState( CStateFactory::EStateLaunchApp ); |
|
2143 #else |
|
2144 SLOG( "Dependencies and application are installed, ready to exit!" ); |
|
2145 iStateMachine.SetState( CStateFactory::EStateExit ); |
|
2146 #endif |
|
2147 } |
|
2148 else |
|
2149 { |
|
2150 SLOG3( "* Installing AppSis 0x%08x '%S'", iStateMachine.iCurrentPackage->GetPackageUid(), iStateMachine.SisFilename() ); |
|
2151 |
|
2152 // TODO: Leave or not to leave? |
|
2153 //User::LeaveIfNull( iStateMachine.SisFilename() ); |
|
2154 |
|
2155 // Update the progress bar |
|
2156 iStateMachine.UpdateProgressBar( iStateMachine.iProgressMaxValue, |
|
2157 iStateMachine.iProgressMaxValue ); |
|
2158 |
|
2159 //First try silent install - if package is self-signed, this will fail |
|
2160 //according to policy, so retry with a normal install. |
|
2161 |
|
2162 //User might not have been prompted for drive selection. |
|
2163 //In that case, it is ok to prompt for drive selection as part of the Wrapper Package Installation. |
|
2164 //This will be the case when files are injected into the Bootstrap import folder and not in a common "?:/ADM" drive. |
|
2165 |
|
2166 TChar installDrive = iStateMachine.SisFilename()->Des()[0]; |
|
2167 installDrive.UpperCase(); |
|
2168 if (installDrive < 'A' || installDrive > 'Z') |
|
2169 { |
|
2170 installDrive = KNoDriveSelected; |
|
2171 } |
|
2172 |
|
2173 // If the wrapper installed drive is not selected, use the application.sis |
|
2174 // destination drive as the installed drive. This way the developer can |
|
2175 // control, if he/she wants to prompt the installation drive or force it |
|
2176 // already in the wrapper/installer .pkg file. This can be controlled |
|
2177 // by using '!' as the destination drive (=prompt) or by using a fixed |
|
2178 // drive letter A->Z (=don't prompt). |
|
2179 if ( iStateMachine.iWrapperInstalledDrive == KNoDriveSelected ) |
|
2180 { |
|
2181 iStateMachine.iWrapperInstalledDrive = installDrive; |
|
2182 } |
|
2183 |
|
2184 if ( iStateMachine.iWrapperInstalledDrive != KNoDriveSelected ) |
|
2185 { |
|
2186 SLOG3( "Installing AppSis '%S' to %c:", iStateMachine.SisFilename(), (char)iStateMachine.iWrapperInstalledDrive ); |
|
2187 |
|
2188 // First show the wait note and then remove progress bar. |
|
2189 // MUCH less flicker this way. |
|
2190 iStateMachine.ShowWaitNoteL( R_ADM_FINALIZING_INSTALLATION_WAIT_TEXT ); |
|
2191 iStateMachine.StopProgressBar(); |
|
2192 iStateMachine.iInstallManager->SilentInstallPackageL( *iStateMachine.SisFilename(), iStateMachine.iWrapperInstalledDrive ); |
|
2193 } |
|
2194 else |
|
2195 { |
|
2196 SLOG( "! No installation drive selected, prompting" ); |
|
2197 // User will be prompted for the drive. |
|
2198 |
|
2199 //TODO: This is a hack. Change the Installcompleted logic to accomodate this. |
|
2200 iStateMachine.StopWaitNote(); |
|
2201 iStateMachine.StopProgressBar(); |
|
2202 TInt aStatus = iStateMachine.iInstallManager-> |
|
2203 InstallPackage( *iStateMachine.SisFilename() ); |
|
2204 iStateMachine.SetNonSilentInstallation(ETrue); |
|
2205 iStateMachine.HandleInstallCompletedL( aStatus ); |
|
2206 } |
|
2207 } // if |
|
2208 } |
|
2209 else |
|
2210 { |
|
2211 // Hmm. We should've had a root package, but apparently we didn't. Odd. |
|
2212 SLOG( "! Unexpected root package. PANIC" ); |
|
2213 PanicInState(EPanicStateUnexpectedRootPackage); |
|
2214 } |
|
2215 } |
|
2216 |
|
2217 void TStateInstallAppSis::InstallCompleted(TInt aStatus) |
|
2218 { |
|
2219 LOG_FUNC |
|
2220 |
|
2221 //It is possible for silent installation of the main app to fail due to insufficient memory |
|
2222 //TODO: would it be wise to move the below conditions to InstallManager and have some different error returned to statemachine? |
|
2223 |
|
2224 if ( ( aStatus == SwiUI::KSWInstErrSecurityFailure ) || ( aStatus == SwiUI::KSWInstErrInsufficientMemory ) ) |
|
2225 { |
|
2226 // We have a wait note displayed. If silent install failed, |
|
2227 // it needs to be removed so the installer UI won't be affected. |
|
2228 iStateMachine.StopWaitNote(); |
|
2229 |
|
2230 //SwiUI collapses the real error, Swi::ESignatureSelfSigned is what we should |
|
2231 //be checking here. SwiUI::GetLastErrorL is not implemented |
|
2232 //If the silent install fails, because of a self signed package, try again |
|
2233 //with interactive install. |
|
2234 // This is a synchronous call which returns the control here after |
|
2235 // installation is finished (or cancelled, or an error occurs or..) |
|
2236 aStatus = iStateMachine.iInstallManager->InstallPackage( |
|
2237 *iStateMachine.SisFilename() ); |
|
2238 iStateMachine.SetNonSilentInstallation(ETrue); |
|
2239 } |
|
2240 else if ( aStatus == KErrNone ) |
|
2241 { |
|
2242 // We end up here, if the silent installation completes succesfully |
|
2243 iStateMachine.SetSilentInstallationOk(ETrue); |
|
2244 } |
|
2245 // Was installation succesful? |
|
2246 if (aStatus == KErrNone) |
|
2247 { |
|
2248 CPackageInfo *curr = iStateMachine.iDepTree->GetCurrentFetchNode(); |
|
2249 User::LeaveIfNull(curr); |
|
2250 //TODO: What if root package is set in HandleInstallComplete!!! |
|
2251 // The next if should _always_ be true here |
|
2252 if ( curr->GetPackageStatus() == EPackageRootToBeInstalled ) |
|
2253 { |
|
2254 curr->SetPackageStatus(EPackageRootInstalled); |
|
2255 } |
|
2256 else if ( curr->GetPackageStatus() != EPackageRootInstalled ) |
|
2257 { |
|
2258 SLOG2( "! Invalid root package status %d", curr->GetPackageStatus() ); |
|
2259 } |
|
2260 |
|
2261 CPackageInfo* fetchPackage = iStateMachine.iDepTree->GetNextFetchNode(); |
|
2262 |
|
2263 // TODO: This is duplicated code from TStateDownloadDependency |
|
2264 if ( !fetchPackage ) |
|
2265 { |
|
2266 /* |
|
2267 //end of list - we're finished |
|
2268 SLOG( "Uninstalling wrapper" ); |
|
2269 TInt err = iStateMachine.iInstallManager->SilentUnInstallPackage( |
|
2270 iStateMachine.WrapperPackageUid() ); |
|
2271 SLOG2( "Uninstall status: %d", err); |
|
2272 // Wrapper has been uninstalled, ready to exit |
|
2273 */ |
|
2274 #ifdef FEATURE_LAUNCH_INSTALLED_APP |
|
2275 iStateMachine.SetState( CStateFactory::EStateLaunchApp ); |
|
2276 #else |
|
2277 iStateMachine.SetState( CStateFactory::EStateExit ); |
|
2278 #endif |
|
2279 return; |
|
2280 } |
|
2281 else |
|
2282 { |
|
2283 // We should be at the end of the list, but seems that we're not. |
|
2284 SLOG2( "! Unexpected package 0x%08X. PANIC", fetchPackage->GetPackageUid() ); |
|
2285 PanicInState(EPanicStateUnexpectedPackage); |
|
2286 } |
|
2287 } |
|
2288 else |
|
2289 { |
|
2290 const TExitReason reason = (aStatus == SwiUI::KSWInstErrUserCancel) |
|
2291 ? EUserCancelled |
|
2292 : EInstallationFailed; |
|
2293 iStateMachine.SetFailureReason( reason ); |
|
2294 iStateMachine.SetState( CStateFactory::EStatePrepareExitWithError ); |
|
2295 } |
|
2296 } |
|
2297 |
|
2298 // ----------------------------------------------------------------------------- |
|
2299 // Confirms the user to continue the download when download threshold is exceeded |
|
2300 // ----------------------------------------------------------------------------- |
|
2301 // |
|
2302 TStateConfirmDownload::TStateConfirmDownload(const CStateFactory& aFactory) : |
|
2303 TState(aFactory) |
|
2304 { |
|
2305 } |
|
2306 |
|
2307 void TStateConfirmDownload::Enter() const |
|
2308 { |
|
2309 // Show download query as we are roaming |
|
2310 iStateMachine.ShowDownloadQueryL( R_ADM_DL_PROMPT_TEXT ); |
|
2311 // the next state will get invoked by the user reply to the query |
|
2312 } |
|
2313 |
|
2314 void TStateConfirmDownload::UserAccepted() |
|
2315 { |
|
2316 // This is called when the user has selected "Yes" in the confirmation query |
|
2317 iStateMachine.SetState( CStateFactory::EStateStartDependencyDownload ); |
|
2318 } |
|
2319 |
|
2320 // ----------------------------------------------------------------------------- |
|
2321 // Confirms the user to continue the download if device is roaming |
|
2322 // ----------------------------------------------------------------------------- |
|
2323 // |
|
2324 TStateConfirmRoamingDownload::TStateConfirmRoamingDownload(const CStateFactory& aFactory) : |
|
2325 TState(aFactory) |
|
2326 { |
|
2327 } |
|
2328 |
|
2329 void TStateConfirmRoamingDownload::Enter() const |
|
2330 { |
|
2331 // Show download query as we are roaming |
|
2332 iStateMachine.ShowDownloadQueryL( R_ADM_DL_PROMPT_TEXT, R_ADM_ROAMING_TEXT ); |
|
2333 // the next state will get invoked by the user reply to the query |
|
2334 } |
|
2335 |
|
2336 void TStateConfirmRoamingDownload::UserAccepted() |
|
2337 { |
|
2338 // This is called when the user has selected "Yes" in the confirmation query |
|
2339 iStateMachine.SetState( CStateFactory::EStateStartDependencyDownload ); |
|
2340 } |