|
1 /* |
|
2 * Copyright (c) 2009 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: ?Description |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include "iaupdatenodecontainer.h" |
|
21 |
|
22 #include "iaupdatecontrollerimpl.h" |
|
23 #include "iaupdatecontentoperationmanager.h" |
|
24 #include "iaupdatenodeimpl.h" |
|
25 #include "iaupdatefwnodeimpl.h" |
|
26 #include "iaupdatenodedetails.h" |
|
27 #include "iaupdatenodedependencyimpl.h" |
|
28 #include "iaupdateplatformdependency.h" |
|
29 #include "iaupdateutils.h" |
|
30 #include "iaupdatenodefactory.h" |
|
31 |
|
32 #include "iaupdatedebug.h" |
|
33 |
|
34 |
|
35 // Constant that is used to inform that dependency node |
|
36 // was not found when dependencies were checked. |
|
37 const TInt KDependencyNotFound( -1 ); |
|
38 |
|
39 |
|
40 CIAUpdateNodeContainer* CIAUpdateNodeContainer::NewLC( |
|
41 CIAUpdateController& aController ) |
|
42 { |
|
43 CIAUpdateNodeContainer *self = |
|
44 new (ELeave) CIAUpdateNodeContainer( aController ); |
|
45 CleanupStack::PushL( self ); |
|
46 self->ConstructL(); |
|
47 return self; |
|
48 } |
|
49 |
|
50 CIAUpdateNodeContainer* CIAUpdateNodeContainer::NewL( |
|
51 CIAUpdateController& aController ) |
|
52 { |
|
53 CIAUpdateNodeContainer *self = |
|
54 CIAUpdateNodeContainer::NewLC( aController ); |
|
55 CleanupStack::Pop( self ); |
|
56 return self; |
|
57 } |
|
58 |
|
59 |
|
60 CIAUpdateNodeContainer::CIAUpdateNodeContainer( |
|
61 CIAUpdateController& aController ) |
|
62 : CBase(), |
|
63 iController( aController ) |
|
64 { |
|
65 } |
|
66 |
|
67 void CIAUpdateNodeContainer::ConstructL() |
|
68 { |
|
69 } |
|
70 |
|
71 |
|
72 CIAUpdateNodeContainer::~CIAUpdateNodeContainer() |
|
73 { |
|
74 Clear(); |
|
75 } |
|
76 |
|
77 |
|
78 void CIAUpdateNodeContainer::AddNodeL( CIAUpdateNode* aNode ) |
|
79 { |
|
80 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::AddNodeL() begin"); |
|
81 |
|
82 if ( !aNode ) |
|
83 { |
|
84 // Null is not acceptable |
|
85 IAUPDATE_TRACE("[IAUPDATE] LEAVE: Node null"); |
|
86 User::Leave( KErrArgument ); |
|
87 } |
|
88 |
|
89 CleanupStack::PushL( aNode ); |
|
90 |
|
91 IAUPDATE_TRACE("[IAUPDATE] Check if node is acceptable"); |
|
92 if ( !NodeAlreadyExists( *aNode ) |
|
93 && aNode->Details().PlatformDependency().AcceptablePlatformL() |
|
94 && InstallCheckL( *aNode ) |
|
95 && !aNode->Details().EmbededDegrades() |
|
96 && PackageTypeAcceptedL( *aNode ) ) |
|
97 { |
|
98 IAUPDATE_TRACE("[IAUPDATE] Node accepted. Add into the node array."); |
|
99 |
|
100 // The node list will contain nodes |
|
101 // that can be downloaded and installed. |
|
102 // The header node list will provide |
|
103 // most recent version of the content. |
|
104 |
|
105 // The ownership of the node transfers. |
|
106 // So try to append it into the array. |
|
107 // If node can not be added into the array, |
|
108 // it will be deleted when appending leaves. |
|
109 iNodes.AppendL( aNode ); |
|
110 // Appending was successfull. |
|
111 // So, ownership has been transferred successfully. |
|
112 CleanupStack::Pop( aNode ); |
|
113 } |
|
114 else |
|
115 { |
|
116 IAUPDATE_TRACE("[IAUPDATE] Node not accepted. Delete it."); |
|
117 |
|
118 // Because the node is not deployable |
|
119 // or it was for the wrong platform, |
|
120 // there is no use for it. Delete the node. |
|
121 CleanupStack::PopAndDestroy( aNode ); |
|
122 } |
|
123 |
|
124 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::AddNodeL() end"); |
|
125 } |
|
126 |
|
127 |
|
128 void CIAUpdateNodeContainer::AddExcessNodeL( CIAUpdateNode* aNode ) |
|
129 { |
|
130 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::AddExcessNodeL() begin"); |
|
131 |
|
132 if ( aNode == NULL ) |
|
133 { |
|
134 // Null is not acceptable |
|
135 IAUPDATE_TRACE("[IAUPDATE] LEAVE: NULL node"); |
|
136 User::Leave( KErrArgument ); |
|
137 } |
|
138 |
|
139 // The node list will contain nodes that do not belong to any other |
|
140 // node category. |
|
141 |
|
142 // The ownership of the node transfers. |
|
143 // So try to append it into the array. |
|
144 CleanupStack::PushL( aNode ); |
|
145 iExcessNodes.AppendL( aNode ); |
|
146 CleanupStack::Pop( aNode ); |
|
147 |
|
148 // Force the node to be hidden. |
|
149 aNode->ForceHidden( ETrue ); |
|
150 |
|
151 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::AddExcessNodeL() end"); |
|
152 } |
|
153 |
|
154 |
|
155 void CIAUpdateNodeContainer::AddFwNodeL( CIAUpdateFwNode* aNode ) |
|
156 { |
|
157 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::AddFwNodeL() begin"); |
|
158 |
|
159 if ( !aNode ) |
|
160 { |
|
161 // Null is not acceptable |
|
162 IAUPDATE_TRACE("[IAUPDATE] LEAVE: Node null"); |
|
163 User::Leave( KErrArgument ); |
|
164 } |
|
165 |
|
166 CleanupStack::PushL( aNode ); |
|
167 |
|
168 iFwNodes.AppendL( aNode ); |
|
169 |
|
170 CleanupStack::Pop( aNode ); |
|
171 |
|
172 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::AddFwNodeL() end"); |
|
173 } |
|
174 |
|
175 |
|
176 void CIAUpdateNodeContainer::Clear() |
|
177 { |
|
178 // Just reset this list because all the nodes |
|
179 // are owned by the iNodes list. |
|
180 iHeadNodes.Reset(); |
|
181 |
|
182 // Reset the list and delete the nodes. |
|
183 iNodes.ResetAndDestroy(); |
|
184 |
|
185 // Reset the list and delete the nodes. |
|
186 iExcessNodes.ResetAndDestroy(); |
|
187 |
|
188 // Reset the list and delete the nodes. |
|
189 iFwNodes.ResetAndDestroy(); |
|
190 } |
|
191 |
|
192 |
|
193 const RPointerArray< CIAUpdateNode >& CIAUpdateNodeContainer::AllNodes() const |
|
194 { |
|
195 return iNodes; |
|
196 } |
|
197 |
|
198 |
|
199 const RPointerArray< CIAUpdateNode >& CIAUpdateNodeContainer::ExcessNodes() const |
|
200 { |
|
201 return iExcessNodes; |
|
202 } |
|
203 |
|
204 |
|
205 const RPointerArray< CIAUpdateNode >& CIAUpdateNodeContainer::HeadNodesL() |
|
206 { |
|
207 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::HeadNodesL() begin"); |
|
208 |
|
209 // Make sure that dependencies are correct. |
|
210 // Notice, that here the dependencies are checked for all the nodes |
|
211 // in the node list. So, some dependencies that may not be required |
|
212 // are also checked. (Unnecessary dependency checks can exist, for example, |
|
213 // if the server sends multiple update packets for a same content version.) |
|
214 // But, checking of dependencies first makes it easier to find correct header |
|
215 // nodes later because we can be sure that all the nodes have intact dependency |
|
216 // chains then. Also, notice that this function will set the information about |
|
217 // the dependency checks into the nodes and remove nodes, whose dependencies |
|
218 // are broken, from the list. |
|
219 UpdateDependenciesL(); |
|
220 |
|
221 // Create the header node list and remove nodes |
|
222 // whose dependency chains are broken. |
|
223 ManageHeaderNodesL(); |
|
224 |
|
225 // Create the dependecy for self update nodes |
|
226 // and mark selfupdater and ncd hidden. |
|
227 // RemoveHiddenNodesFromHeadList will handle those nodes |
|
228 // after they have been marked hidden. |
|
229 CreateSelfUpdateBundleL(); |
|
230 |
|
231 // This will set the service pack dependency nodes as hidden. |
|
232 HandleServicePacksL(); |
|
233 |
|
234 // Bundles may contain nodes that are head nodes |
|
235 // but have been marked hidden. |
|
236 // So, remove hidden nodes from the head list. |
|
237 // Hidden nodes should be visible to UI. |
|
238 RemoveHiddenNodesFromHeadList(); |
|
239 |
|
240 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::HeadNodesL() end"); |
|
241 |
|
242 return iHeadNodes; |
|
243 } |
|
244 |
|
245 |
|
246 const RPointerArray< CIAUpdateFwNode >& CIAUpdateNodeContainer::FwNodes() |
|
247 { |
|
248 return iFwNodes; |
|
249 } |
|
250 |
|
251 |
|
252 void CIAUpdateNodeContainer::UpdateDependenciesL() |
|
253 { |
|
254 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::UpdateDependenciesL() begin"); |
|
255 |
|
256 // Reset node statuses |
|
257 for ( TInt i = 0; i < iNodes.Count(); ++i ) |
|
258 { |
|
259 iNodes[ i ]->Reset(); |
|
260 } |
|
261 |
|
262 // Check and update the dependencies for all the nodes. |
|
263 // So, it will be checked that all the nodes can be installed correctly |
|
264 // and no dependencies for them are missing. |
|
265 for ( TInt i = 0; i < iNodes.Count(); ++i ) |
|
266 { |
|
267 // If the node dependency status has already been set, |
|
268 // then it was already checked in some previous loop |
|
269 // or recursion of dependency check. So, do not recheck |
|
270 // the same branch here. Notice, the DependencyCheckStatus is |
|
271 // also checked in the recursion in UpdateNodeDependenciesL. |
|
272 // So, recheck should not even be allowed here. Otherwise checks |
|
273 // will fail unless the statuses are resetted before. |
|
274 // If the state has not been set, then check the branch. |
|
275 CIAUpdateNode& node( *iNodes[ i ] ); |
|
276 if ( node.DependencyCheckStatus() |
|
277 == CIAUpdateNode::EDependencyCheckNotSet ) |
|
278 { |
|
279 // Notice, that this function sets the dependency check status |
|
280 // for the node and to the nodes belonging to that branch in |
|
281 // its dependency tree. |
|
282 UpdateNodeDependenciesL( node, 0 ); |
|
283 } |
|
284 } |
|
285 |
|
286 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::UpdateDependenciesL() end"); |
|
287 } |
|
288 |
|
289 |
|
290 TInt CIAUpdateNodeContainer::UpdateNodeDependenciesL( |
|
291 CIAUpdateNode& aNode, TInt aDepth ) |
|
292 { |
|
293 IAUPDATE_TRACE_2("[IAUPDATE] CIAUpdateNodeContainer::UpdateNodeDependenciesL() begin: %S, %S", |
|
294 &aNode.MetaNamespace(), &aNode.MetaId()); |
|
295 |
|
296 // Notice that this function creates a recursive loop together with |
|
297 // FindBestMatchL function. |
|
298 |
|
299 // Check if we have already handled this node and dependency loops back to it. |
|
300 // If node check is already going on for the node, then there is loop in dependency. |
|
301 // Do not accept loops for dependencies. If no loop, then continue normally. |
|
302 // Notice, that if we loop here, other sub branches may have not been |
|
303 // checked for this node yet. So, only set the status when the whole subtree has |
|
304 // been checked. |
|
305 |
|
306 if ( aNode.DependencyCheckStatus() |
|
307 == CIAUpdateNode::EDependencyCheckNotSet ) |
|
308 { |
|
309 IAUPDATE_TRACE("[IAUPDATE] Dependency check not set yet"); |
|
310 |
|
311 // Gives the total leaf distance of this part of the dependency tree. |
|
312 // The tallest branch gives the total leaf distance. |
|
313 TInt totalLeafDistance( KDependencyNotFound ); |
|
314 |
|
315 // Mark the check state here to prevent loops. |
|
316 aNode.SetDependencyCheckStatus( CIAUpdateNode::EDependencyCheckGoing ); |
|
317 |
|
318 RPointerArray< CIAUpdateNodeDependency > deps; |
|
319 CleanupClosePushL( deps ); |
|
320 |
|
321 // Get dependency objects from aNode into the deps array. |
|
322 // Get dependencies that were gotten from the server. |
|
323 aNode.Details().GetDependenciesL( deps ); |
|
324 |
|
325 // Now, that we have the dependency information for the given node, |
|
326 // find the nodes that provide the best dependency branches. |
|
327 for ( TInt i = 0; i < deps.Count(); ++i ) |
|
328 { |
|
329 // The best branch is thought to be the branch that is the flattest. |
|
330 // FindBestMatchL function inserts the best match information |
|
331 // to the dependency object. The best match information of the dependency |
|
332 // will contain the possible node whose content is required |
|
333 // for the dependency chain to be complete. Also, that node may need other nodes. |
|
334 // So, the dependency branch may continue there. |
|
335 // Dependency depth is one greater than the depth of dependant aNode. |
|
336 TInt leafDistance( |
|
337 FindBestMatchL( aNode, *deps[ i ], aDepth + 1 ) ); |
|
338 |
|
339 // Notice, that here we are looking for the total leaf distance for this branch. |
|
340 // FindBestMatchL -function that is used above will use this value to check |
|
341 // what branch has the shortes totalLeafDistance. |
|
342 // The branch that is flattest will be chosen for the current parent node. |
|
343 if ( leafDistance == KDependencyNotFound ) |
|
344 { |
|
345 IAUPDATE_TRACE("[IAUPDATE] Dependency check failed"); |
|
346 |
|
347 // Because dependency was not found from the node list or from |
|
348 // the installed applications, the node dependency chain is broken. |
|
349 // Set this information into the node. |
|
350 // So, this node will be removed from the node list later. |
|
351 aNode.SetDependencyCheckStatus( CIAUpdateNode::EDependencyCheckFailed ); |
|
352 |
|
353 // Because, one missing item is enough to break the chain, just return here. |
|
354 // If other nodes are required, they are checked separately later in their own |
|
355 // checkings. The chain break affects all the nodes that depend on this one. So, |
|
356 // this information will be set to the nodes, when the recursion goes back. |
|
357 CleanupStack::PopAndDestroy( &deps ); |
|
358 |
|
359 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::UpdateNodeDependenciesL() end: KDependencyNotFound"); |
|
360 |
|
361 return KDependencyNotFound; |
|
362 } |
|
363 else if ( totalLeafDistance < leafDistance ) |
|
364 { |
|
365 IAUPDATE_TRACE_2("[IAUPDATE] Replace old totalLeafDistance %d, %d", |
|
366 totalLeafDistance, leafDistance); |
|
367 // Set the total leaf distance of this part of the dependency chain because |
|
368 // the chain is intact. |
|
369 totalLeafDistance = leafDistance; |
|
370 } |
|
371 } |
|
372 |
|
373 CleanupStack::PopAndDestroy( &deps ); |
|
374 |
|
375 // Dependency chain for the node is intact. |
|
376 // Set this information into the node. |
|
377 aNode.SetDependencyCheckStatus( CIAUpdateNode::EDependencyCheckPassed ); |
|
378 IAUPDATE_TRACE("[IAUPDATE] EDependencyCheckPassed"); |
|
379 |
|
380 // Add one, so the parent will get its own actual leaf distance in return. |
|
381 ++totalLeafDistance; |
|
382 |
|
383 // Also, set the total leaf distance for the node. |
|
384 aNode.SetLeafDistance( totalLeafDistance ); |
|
385 |
|
386 |
|
387 IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateNodeContainer::UpdateNodeDependenciesL() end: %d", |
|
388 totalLeafDistance); |
|
389 |
|
390 return totalLeafDistance; |
|
391 } |
|
392 else if ( aNode.DependencyCheckStatus() |
|
393 == CIAUpdateNode::EDependencyCheckPassed ) |
|
394 { |
|
395 IAUPDATE_TRACE("[IAUPDATE] Dependency check already passed"); |
|
396 |
|
397 // Because this node and the hierarchy below it has already been handled, |
|
398 // check if the depth of the node and its dependency hierarchy should be |
|
399 // updated with the new value. |
|
400 aNode.UpdateDependencyDepthsL( aDepth ); |
|
401 |
|
402 // Because we have already handled this branch successfully, |
|
403 // just return its own leaf distance information. |
|
404 IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateNodeContainer::UpdateNodeDependenciesL() end: %d", |
|
405 aNode.LeafDistance()); |
|
406 return aNode.LeafDistance(); |
|
407 } |
|
408 else if ( aNode.DependencyCheckStatus() |
|
409 == CIAUpdateNode::EDependencyCheckGoing ) |
|
410 { |
|
411 IAUPDATE_TRACE("[IAUPDATE] Dependency loop has occurred"); |
|
412 // Notice, we come here if there are loops in dependencies. |
|
413 // Looping dependency chains are not acceptable in normal cases. |
|
414 // Notice, in case of service packs, if another branch of service pack |
|
415 // is intact and it does not loop, then the service pack check status |
|
416 // is set to CIAUpdateNode::EDependencyCheckPassed when the recursion |
|
417 // is over above and all the branches of the service pack have been handled. |
|
418 // Still loopin branches inside service pack will also be removed. |
|
419 aNode.SetDependencyCheckStatus( CIAUpdateNode::EDependencyCheckFailed ); |
|
420 } |
|
421 |
|
422 // We come here if dependency check status has been set to |
|
423 // CIAUpdateNode::EDependencyCheckFailed. So, then always |
|
424 // return KDependencyNotFound to correspond that situation. |
|
425 |
|
426 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::UpdateNodeDependenciesL() end: KDependencyNotFound"); |
|
427 |
|
428 return KDependencyNotFound; |
|
429 } |
|
430 |
|
431 |
|
432 TInt CIAUpdateNodeContainer::FindBestMatchL( CIAUpdateNode& aNode, |
|
433 CIAUpdateNodeDependency& aDependency, |
|
434 TInt aDependencyDepth ) |
|
435 { |
|
436 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::FindBestMatchL() begin"); |
|
437 |
|
438 // Notice that this function creates a recursive loop together with |
|
439 // UpdateNodeDependenciesL function. |
|
440 |
|
441 // As a default, the dependency we are looking for is marked as not found. |
|
442 TInt totalLeafDistance( KDependencyNotFound ); |
|
443 |
|
444 // Check if the dependency file has already been installed and get the version |
|
445 // of the application if it has been installed. |
|
446 TIAUpdateVersion installedVersion; |
|
447 TBool installed( |
|
448 IAUpdateUtils::IsAppInstalledL( |
|
449 aDependency.Uid(), installedVersion ) ); |
|
450 |
|
451 if ( aDependency.IsEmbedded() ) |
|
452 { |
|
453 IAUPDATE_TRACE("[IAUPDATE] Dependency is embedded in the node."); |
|
454 // If dependency node is already embedded into the package, then use it |
|
455 // instead of downloading it separately. Embedded dependencies are always |
|
456 // matched by the node itself. Embedded package has to be installed |
|
457 // when content is installed, or the whole installation fails. |
|
458 // Best match for this dependency is the node content itself. But, |
|
459 // to prevent loops, set the best match to NULL. |
|
460 aDependency.SetBestMatch( NULL ); |
|
461 |
|
462 // If the embedded node will require downgrades, |
|
463 // then do not accept this dependency. Notice, here we think |
|
464 // that the embedded content version value is given as version roof value. |
|
465 // So, the installed version has to be equal or smaller than the roof value, |
|
466 // if the embedded content can be accepted. |
|
467 // Note for future improvements: |
|
468 // When support is added for embedded sisx to have dependencies, |
|
469 // this needs to be changed accordingly |
|
470 if ( !installed |
|
471 || installedVersion <= aDependency.VersionRoof() ) |
|
472 { |
|
473 IAUPDATE_TRACE("[IAUPDATE] Embedded content can be installed"); |
|
474 // Leaf distance is zero because embedded item is already part |
|
475 // of the node itself. |
|
476 totalLeafDistance = 0; |
|
477 } |
|
478 } |
|
479 else |
|
480 { |
|
481 IAUPDATE_TRACE("[IAUPDATE] Dependency content is not embedded."); |
|
482 |
|
483 // Check here if the best matching content is already installed or if |
|
484 // content needs to be downloaded and installed |
|
485 |
|
486 // Note, that the dependency may also describe an update dependency |
|
487 // for the content instead of just describing that a content depends |
|
488 // on another content. But, we can handle it all these cases in a same |
|
489 // way. |
|
490 |
|
491 // This value will be updated when the recursive call of |
|
492 // UpdateNodeDependenciesL inside for-loop has found an acceptable leaf node. |
|
493 // Then, recursion will come back of the tree hierarchy and find other branches |
|
494 // and update this value if necessary. |
|
495 CIAUpdateNode* currentBestMatch( NULL ); |
|
496 |
|
497 RPointerArray< CIAUpdateNode > matches; |
|
498 CleanupClosePushL( matches ); |
|
499 |
|
500 // Find the nodes that fullfill the given dependency requirement. |
|
501 // Node list may contain multiple alternatives. |
|
502 // So, first find the alternatives. |
|
503 // Notice, that this function skips already installed items. |
|
504 FindMatchesL( matches, aDependency ); |
|
505 |
|
506 // Find the best match from the alternatives. |
|
507 for ( TInt i = 0; i < matches.Count(); ++i ) |
|
508 { |
|
509 CIAUpdateNode& tmpNode( *matches[ i ] ); |
|
510 |
|
511 // The node that matches can be part of the best dependency branch. |
|
512 // But, we still need to check the whole branch before we can be sure. |
|
513 // So, check the dependency branch forward by using the recursion. |
|
514 TInt leafDistance( |
|
515 UpdateNodeDependenciesL( tmpNode, aDependencyDepth ) ); |
|
516 |
|
517 // If no match has been handled so far, then the new one is best match. |
|
518 // If there is already a current best match, then check if the |
|
519 // new one should replace it. |
|
520 if ( leafDistance != KDependencyNotFound |
|
521 && ( totalLeafDistance == KDependencyNotFound |
|
522 || currentBestMatch |
|
523 && ReplaceRecommendedL( |
|
524 *currentBestMatch, tmpNode ) ) ) |
|
525 { |
|
526 IAUPDATE_TRACE("[IAUPDATE] New best match found."); |
|
527 currentBestMatch = &tmpNode; |
|
528 totalLeafDistance = leafDistance; |
|
529 } |
|
530 } |
|
531 |
|
532 CleanupStack::PopAndDestroy( &matches ); |
|
533 |
|
534 // Set the best match information for the dependency. |
|
535 // Notice, that if installedVersion equals the currentBestMatch version, |
|
536 // the node is set instead of NULL value. This way if a content in the |
|
537 // middle of the dependency chain is installed, the dependency way will |
|
538 // not be cut in that place. |
|
539 if ( installed |
|
540 && installedVersion >= aDependency.VersionFloor() |
|
541 && installedVersion <= aDependency.VersionRoof() |
|
542 && ( !currentBestMatch |
|
543 || installedVersion > currentBestMatch->Version() ) ) |
|
544 { |
|
545 IAUPDATE_TRACE("[IAUPDATE] Best dependency content is already installed. Use it."); |
|
546 // The content was already installed and its version belonged |
|
547 // to the required version range. Also, the installed version |
|
548 // was greater than the version of other matches. |
|
549 // The best match was found, but it requires no nodes and their content. |
|
550 aDependency.SetBestMatch( NULL ); |
|
551 totalLeafDistance = 0; |
|
552 } |
|
553 else |
|
554 { |
|
555 IAUPDATE_TRACE("[IAUPDATE] Use current best match item if available"); |
|
556 // If currentBestMatch is not NULL, the best dependency node was found. |
|
557 // If currentBestMatch is NULL, the best dependency node was not found. |
|
558 // So, just set the best match information accordingly. |
|
559 aDependency.SetBestMatch( currentBestMatch ); |
|
560 if ( currentBestMatch ) |
|
561 { |
|
562 IAUPDATE_TRACE("[IAUPDATE] Current best match item is available"); |
|
563 |
|
564 // Notice, that UpdateNodeDependenciesL checks and prevents looping. |
|
565 // So, no need to do it here. AddDependant now, that we found the |
|
566 // best match. Notice, we only want to insert dependant information |
|
567 // to the correct item not to possible choices. So, that is why we |
|
568 // do it here, not inside the for-loop above. |
|
569 currentBestMatch->AddDependantL( aNode ); |
|
570 |
|
571 // Because node depth has not been set yet, update it now. |
|
572 // Notice, we update the depth here because then the depth |
|
573 // will be updated only to the best match node. In other words, |
|
574 // the depth is updated only to the nodes that will be used. |
|
575 // So, depths of other nodes that are skipped are not updated. |
|
576 // This way the depth information will be correct if different |
|
577 // nodes required alternative dependency hierarchies from some |
|
578 // content. |
|
579 currentBestMatch-> |
|
580 UpdateDependencyDepthsL( aDependencyDepth ); |
|
581 } |
|
582 } |
|
583 } |
|
584 |
|
585 IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateNodeContainer::FindBestMatchL() end: %d", |
|
586 totalLeafDistance); |
|
587 |
|
588 return totalLeafDistance; |
|
589 } |
|
590 |
|
591 |
|
592 void CIAUpdateNodeContainer::FindMatchesL( RPointerArray< CIAUpdateNode >& aNodes, |
|
593 const CIAUpdateNodeDependency& aDependency ) |
|
594 { |
|
595 // Find all the matching nodes from the node list. |
|
596 for( TInt i = 0; i < iNodes.Count(); ++i ) |
|
597 { |
|
598 CIAUpdateNode& node( *iNodes[ i ] ); |
|
599 // Check if the node matches the given dependency. |
|
600 if( node.Uid() == aDependency.Uid() |
|
601 && node.Version() >= aDependency.VersionFloor() |
|
602 && node.Version() <= aDependency.VersionRoof() |
|
603 && InstallCheckL( node ) ) |
|
604 { |
|
605 // Append the matching node into the given list. |
|
606 aNodes.AppendL( &node ); |
|
607 } |
|
608 } |
|
609 } |
|
610 |
|
611 |
|
612 void CIAUpdateNodeContainer::ManageHeaderNodesL() |
|
613 { |
|
614 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::ManageHeaderNodesL() begin"); |
|
615 |
|
616 for ( TInt i = iNodes.Count() - 1; i >= 0; --i ) |
|
617 { |
|
618 CIAUpdateNode& node( *iNodes[ i ] ); |
|
619 if ( node.DependencyCheckStatus() |
|
620 != CIAUpdateNode::EDependencyCheckPassed ) |
|
621 { |
|
622 // The node dependency chain has either failed |
|
623 // or the nodes are not needed |
|
624 // because their dependency status has not been set. |
|
625 // So, remove these nodes from the node list. |
|
626 IAUPDATE_TRACE_2("[IAUPDATE] Node dependency chain broken or node not needed: %S, %S", |
|
627 &node.MetaNamespace(), &node.MetaId()); |
|
628 delete iNodes[ i ]; |
|
629 iNodes[ i ] = NULL; |
|
630 iNodes.Remove( i ); |
|
631 } |
|
632 else |
|
633 { |
|
634 // Notice, that dependencies have been handled |
|
635 // for every item previously. So, now we can choose |
|
636 // the header nodes whose dependencies are intact. |
|
637 // Update the header list to contain newer version |
|
638 // of nodes whose contents have not been installed yet. |
|
639 UpdateHeadNodeListL( node ); |
|
640 } |
|
641 } |
|
642 |
|
643 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::ManageHeaderNodesL() end"); |
|
644 } |
|
645 |
|
646 |
|
647 void CIAUpdateNodeContainer::UpdateHeadNodeListL( CIAUpdateNode& aNode ) |
|
648 { |
|
649 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::UpdateHeadNodeListL() begin"); |
|
650 |
|
651 // All nodes that are not installed yet are possible head nodes. |
|
652 // The final list will contain head nodes that are most recent |
|
653 // versions of nodes that can be downloaded and/or installed. |
|
654 |
|
655 if( !aNode.IsInstalled() ) |
|
656 { |
|
657 IAUPDATE_TRACE("[IAUPDATE] Not installed yet."); |
|
658 |
|
659 // Only consider the highest version of nodes as head nodes. |
|
660 |
|
661 // This flag informs if the node should be appended into the list |
|
662 // because it was not inserted in the for-loop |
|
663 // or if the correct node was already in the list. |
|
664 TBool alreadyIncluded( EFalse ); |
|
665 |
|
666 for ( TInt i = 0; i < iHeadNodes.Count(); ++i ) |
|
667 { |
|
668 CIAUpdateNode& tmpNode( *iHeadNodes[ i ] ); |
|
669 if( aNode.Uid() == tmpNode.Uid() && aNode.Type() != MIAUpdateNode::EPackageTypeServicePack ) //MTA: Changed!!! |
|
670 { |
|
671 IAUPDATE_TRACE("[IAUPDATE] Head node already in the list."); |
|
672 |
|
673 // Node for the corresponding content already exists in the list. |
|
674 // Replace node from the list if the new node is better choice. |
|
675 if ( ReplaceRecommendedL( tmpNode, aNode ) ) |
|
676 { |
|
677 IAUPDATE_TRACE("[IAUPDATE] Replace existing head node"); |
|
678 iHeadNodes[ i ] = &aNode; |
|
679 // Because the old node was removed from the head list, |
|
680 // it is not head node anymore. Set it as hidden. So, |
|
681 // it will be handled correctly when downloading |
|
682 // and installing is done. For example, if the new node |
|
683 // depends on the older version. |
|
684 tmpNode.ForceHidden( ETrue ); |
|
685 } |
|
686 else |
|
687 { |
|
688 IAUPDATE_TRACE("[IAUPDATE] Existing head node stays in head list"); |
|
689 // The existing head node is newer. So, the recommended new node |
|
690 // will not be head node. Make sure that it is set as hidden |
|
691 // because hidden value is used to check if the node is head node |
|
692 // or not. |
|
693 aNode.ForceHidden( ETrue ); |
|
694 } |
|
695 |
|
696 // We found a corresponding item from the head list. |
|
697 // Now, the correct node is in the list. |
|
698 alreadyIncluded = ETrue; |
|
699 break; |
|
700 } |
|
701 } |
|
702 |
|
703 if( !alreadyIncluded ) |
|
704 { |
|
705 // The given node was not inserted above. |
|
706 // So, append it now to the end of the list. |
|
707 // Notice, that here we still may append hidden node into the head |
|
708 // list. This way, the newest node is always in the head list when |
|
709 // comparison is done. Later RemoveHiddenNodesFromHeadList |
|
710 // is called. If the head node is hidden, it will be removed from |
|
711 // the head list. This way we can be sure that head list contains |
|
712 // only newest nodes and no visible head node version is older than |
|
713 // some hidden one. |
|
714 IAUPDATE_TRACE("[IAUPDATE] Add new head node into the list."); |
|
715 iHeadNodes.AppendL( &aNode ); |
|
716 } |
|
717 } |
|
718 |
|
719 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::UpdateHeadNodeListL() begin"); |
|
720 } |
|
721 |
|
722 |
|
723 TBool CIAUpdateNodeContainer::ReplaceRecommendedL( |
|
724 const CIAUpdateNode& aCurrentNode, |
|
725 const CIAUpdateNode& aNewNode ) const |
|
726 { |
|
727 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::ReplaceRecommendedL() begin"); |
|
728 |
|
729 if ( aCurrentNode.Uid() != aNewNode.Uid() ) |
|
730 { |
|
731 IAUPDATE_TRACE("[IAUPDATE] LEAVE: Nodes do not match."); |
|
732 User::Leave( KErrArgument ); |
|
733 } |
|
734 |
|
735 // New node is recommended if encountered node has higher version, |
|
736 // or if the version is equal but current node packet type is |
|
737 // not preferred. Also, the leaf distance of dependency chain is checked |
|
738 // because long dependency chains should be avoided. |
|
739 // The content package order is: (first) PU, SP, SA |
|
740 // Notice, that PU and SP require already installed version of |
|
741 // the application but this was already checked when node were added |
|
742 // into the array. |
|
743 if ( aNewNode.Version() > aCurrentNode.Version() |
|
744 || aNewNode.Version() == aCurrentNode.Version() |
|
745 && aNewNode.LeafDistance() <= aCurrentNode.LeafDistance() |
|
746 && ( aNewNode.Type() == aCurrentNode.Type() |
|
747 || aNewNode.Type() != MIAUpdateNode::EPackageTypeSA |
|
748 && aCurrentNode.Type() == MIAUpdateNode::EPackageTypeSA |
|
749 || aNewNode.Type() == MIAUpdateNode::EPackageTypePU |
|
750 && aCurrentNode.Type() == MIAUpdateNode::EPackageTypeSP ) ) |
|
751 { |
|
752 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::ReplaceRecommendedL() end: ETrue"); |
|
753 return ETrue; |
|
754 } |
|
755 else |
|
756 { |
|
757 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::ReplaceRecommendedL() end: EFalse"); |
|
758 return EFalse; |
|
759 } |
|
760 } |
|
761 |
|
762 |
|
763 TBool CIAUpdateNodeContainer::PackageTypeAcceptedL( |
|
764 const CIAUpdateNode& aNode ) const |
|
765 { |
|
766 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::PackageTypeAcceptedL() begin"); |
|
767 |
|
768 if ( aNode.Type() == MIAUpdateNode::EPackageTypeServicePack |
|
769 || aNode.Type() == MIAUpdateNode::EPackageTypeSA ) |
|
770 { |
|
771 // Service packs and SA type always accepted. |
|
772 IAUPDATE_TRACE("[IAUPDATE] Upgrade packet type SA or node is service pack"); |
|
773 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::PackageTypeAcceptedL() end: ETrue"); |
|
774 return ETrue; |
|
775 } |
|
776 |
|
777 TBool accepted( EFalse ); |
|
778 |
|
779 // The PU and SP packet types are accepted only if |
|
780 // the content that will be updated already exists in the phone. |
|
781 // Otherwise, the SA should be used. |
|
782 RPointerArray< CIAUpdateNodeDependency > dependencies; |
|
783 CleanupClosePushL( dependencies ); |
|
784 |
|
785 aNode.Details().GetDependenciesL( dependencies ); |
|
786 |
|
787 for ( TInt i = 0; i < dependencies.Count(); ++i ) |
|
788 { |
|
789 CIAUpdateNodeDependency* dep( dependencies[ i ] ); |
|
790 if ( aNode.Uid() == dep->Uid() ) |
|
791 { |
|
792 // This dependency describes the upgrade dependency |
|
793 // because the UIDs match. So, now we check if |
|
794 // the upgrade dependency content is available in the phone. |
|
795 TIAUpdateVersion version; |
|
796 |
|
797 // Check if the dependency file has already been installed |
|
798 // and get the version of the application if it has been installed. |
|
799 TBool installed = |
|
800 IAUpdateUtils::IsAppInstalledL( dep->Uid(), version ); |
|
801 |
|
802 if ( installed |
|
803 && version >= dep->VersionFloor() |
|
804 && version <= dep->VersionRoof() ) |
|
805 { |
|
806 // The content was already installed and its version belonged |
|
807 // to the required version range. So, upgrade content is accepted. |
|
808 IAUPDATE_TRACE("[IAUPDATE] Accepted"); |
|
809 accepted = ETrue; |
|
810 break; |
|
811 } |
|
812 } |
|
813 } |
|
814 |
|
815 // If dependencies to the previous versions of |
|
816 // the same content were not found, PU and SP are not accepted. |
|
817 CleanupStack::PopAndDestroy( &dependencies ); |
|
818 |
|
819 IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateNodeContainer::PackageTypeAcceptedL() end: %d", |
|
820 accepted); |
|
821 |
|
822 return accepted; |
|
823 } |
|
824 |
|
825 |
|
826 TBool CIAUpdateNodeContainer::NodeAlreadyExists( const CIAUpdateNode& aNode ) const |
|
827 { |
|
828 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::NodeAlreadyExists() begin"); |
|
829 |
|
830 CIAUpdateNode* node( NULL ); |
|
831 for ( TInt i = 0; i < iNodes.Count(); ++i ) |
|
832 { |
|
833 node = iNodes[ i ]; |
|
834 if ( node->Equals( aNode ) ) |
|
835 { |
|
836 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::NodeAlreadyExists() end: ETrue"); |
|
837 return ETrue; |
|
838 } |
|
839 } |
|
840 |
|
841 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::NodeAlreadyExists() end: EFalse"); |
|
842 |
|
843 return EFalse; |
|
844 } |
|
845 |
|
846 |
|
847 void CIAUpdateNodeContainer::CreateSelfUpdateBundleL() |
|
848 { |
|
849 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::CreateSelfUpdateBundleL() begin"); |
|
850 |
|
851 // Check if IAD exists and if self updater and NCD exist. |
|
852 // Mark self updater and NCD hidden if necessary. |
|
853 // Then, RemoveHiddenNodesFromHeadList will handle rest |
|
854 // when it is called later in the head list creation process. |
|
855 |
|
856 CIAUpdateNode* iad( NULL ); |
|
857 CIAUpdateNode* ncd( NULL ); |
|
858 CIAUpdateNode* selfUpdater( NULL ); |
|
859 |
|
860 for ( TInt i = 0; i < iHeadNodes.Count(); ++i ) |
|
861 { |
|
862 CIAUpdateNode* node( iHeadNodes[ i ] ); |
|
863 const TUid& nodeUid( node->Uid() ); |
|
864 |
|
865 if ( IAUpdateNodeFactory::IsIad( nodeUid ) ) |
|
866 { |
|
867 iad = node; |
|
868 } |
|
869 else if ( IAUpdateNodeFactory::IsNcd( nodeUid ) ) |
|
870 { |
|
871 ncd = node; |
|
872 } |
|
873 else if ( IAUpdateNodeFactory::IsUpdater( nodeUid ) ) |
|
874 { |
|
875 selfUpdater = node; |
|
876 } |
|
877 } |
|
878 |
|
879 // If IAD is given, then other self update related items should |
|
880 // be set hidden. |
|
881 if ( iad ) |
|
882 { |
|
883 IAUPDATE_TRACE("[IAUPDATE] IAD"); |
|
884 // Because IAD is given, the possible NCD and self updater nodes |
|
885 // should be set hidden and dependencies should be created for |
|
886 // self update bundle. |
|
887 // Notice, here we create the forced dependencies only from IAD. |
|
888 if ( ncd ) |
|
889 { |
|
890 IAUPDATE_TRACE("[IAUPDATE] NCD"); |
|
891 // Make NCD hidden and force IAD to depend on it. |
|
892 ncd->ForceHidden( ETrue ); |
|
893 // SetExcessDependencyL will also update the dependant info |
|
894 // for the dependency node. |
|
895 iad->SetExcessDependencyL( *ncd, ETrue ); |
|
896 |
|
897 // Because there is possibility that some service pack items |
|
898 // depend on NCD but do not depend on IAD we need to force |
|
899 // the dependency to IAD. This way if that service pack is |
|
900 // chosen, the IAD that is visible in UI will also be chosen |
|
901 // in UI and the flow can continue correctly. If IAD would not |
|
902 // be forced, then NCD would not be installed because at the |
|
903 // moment service packs do not support self update in IAD Engine |
|
904 // side. If IAD does not exist, then NCD will be shown in UI |
|
905 // and it would be selected if dependency requires that. |
|
906 TInt ncdDependantCount( ncd->DependantNodes().Count() ); |
|
907 const RPointerArray< CIAUpdateNode >& ncdDependants( |
|
908 ncd->DependantNodes() ); |
|
909 IAUPDATE_TRACE_1("[IAUPDATE] Ncd dependant count: %d", |
|
910 ncdDependantCount); |
|
911 for ( TInt i = 0; i < ncdDependantCount; ++i ) |
|
912 { |
|
913 CIAUpdateNode* ncdDependantNode( |
|
914 ncdDependants[ i ] ); |
|
915 if ( iad != ncdDependantNode ) |
|
916 { |
|
917 IAUPDATE_TRACE("[IAUPDATE] NCD dependant gets IAD as dependency"); |
|
918 // The dependant was not iad itself. |
|
919 // Force dependant to depend also from iad. |
|
920 ncdDependantNode->SetExcessDependencyL( *iad, ETrue ); |
|
921 } |
|
922 } |
|
923 } |
|
924 if ( selfUpdater ) |
|
925 { |
|
926 IAUPDATE_TRACE("[IAUPDATE] Selfupdater"); |
|
927 // Make selfupdater hidden and force IAD to depend on it. |
|
928 selfUpdater->ForceHidden( ETrue ); |
|
929 // SetExcessDependencyL will also update the dependant info |
|
930 // for the dependency node. |
|
931 iad->SetExcessDependencyL( *selfUpdater, ETrue ); |
|
932 } |
|
933 } |
|
934 |
|
935 // Above, dependencies were forced to make sure that self update |
|
936 // bunlde is created and the self udpate flow will handle the items |
|
937 // in correct order. Now, make sure that self updater depth and |
|
938 // leaf distance are correct if both ncd and self updater exist. |
|
939 // There is at least some sort of dependency also between them. |
|
940 if ( selfUpdater && ncd ) |
|
941 { |
|
942 IAUPDATE_TRACE("[IAUPDATE] Self updater dependency for NCD"); |
|
943 // Because NCD also requires self updater for its install, |
|
944 // set the dependency depth and leaf distances also here. |
|
945 // Then, the update flow will always try to install self |
|
946 // updater before NCD. Notice, if server has not defined |
|
947 // the dependency between selfupdater and NCD, then do not |
|
948 // force the dependency here either. |
|
949 // In case of IAD, the items will be hidden from UI. |
|
950 // Then, forced dependency chains will not change functionality |
|
951 // in UI. But, if IAD was missing and only NCD and selfupdater would |
|
952 // exist, NCD and self updater should be shown in UI themselves. Then, |
|
953 // UI side should not force dependency between those items, unless |
|
954 // dependency is given in metadata. That is why we do not force |
|
955 // excess dependency into the dependency chain here. Notice, that |
|
956 // if IAD exists, then selfupdater is forced to its dependency above. |
|
957 // So, self updater is part of the IAD bundle then. |
|
958 ncd->SetExcessDependencyL( *selfUpdater, EFalse ); |
|
959 } |
|
960 |
|
961 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::CreateSelfUpdateBundleL() end"); |
|
962 } |
|
963 |
|
964 |
|
965 void CIAUpdateNodeContainer::RemoveHiddenNodesFromHeadList() |
|
966 { |
|
967 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::RemoveHiddenNodesFromHeadList() begin"); |
|
968 |
|
969 TInt count( iHeadNodes.Count() ); |
|
970 for ( TInt i = count - 1; i >= 0; --i ) |
|
971 { |
|
972 CIAUpdateNode* node( iHeadNodes[ i ] ); |
|
973 if ( node->Hidden() ) |
|
974 { |
|
975 // Node is not deleted here because it is still part of the |
|
976 // iNodes list that contains all the nodes. |
|
977 IAUPDATE_TRACE("[IAUPDATE] Remove node"); |
|
978 iHeadNodes.Remove( i ); |
|
979 } |
|
980 } |
|
981 |
|
982 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::RemoveHiddenNodesFromHeadList() begin"); |
|
983 } |
|
984 |
|
985 |
|
986 void CIAUpdateNodeContainer::HandleServicePacksL() |
|
987 { |
|
988 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::HandleServicePacksL() begin"); |
|
989 |
|
990 // This array will contain the nodes that belong to |
|
991 // the dependency hierarchy of the service pack. |
|
992 RPointerArray< CIAUpdateNode > servicePackNodes; |
|
993 CleanupClosePushL( servicePackNodes ); |
|
994 |
|
995 // Notice, here that we will force all the items under the found service pack |
|
996 // as hidden. The main service pack will be shown in UI and possible service packs |
|
997 // in dependencies will be hidden. |
|
998 |
|
999 for ( TInt i = 0; i < iNodes.Count(); ++i ) |
|
1000 { |
|
1001 CIAUpdateNode& node( *iNodes[ i ] ); |
|
1002 if ( node.Type() == MIAUpdateNode::EPackageTypeServicePack ) |
|
1003 { |
|
1004 IAUPDATE_TRACE("[IAUPDATE] Service pack node found"); |
|
1005 |
|
1006 if ( node.IsInstalled() ) |
|
1007 { |
|
1008 IAUPDATE_TRACE("[IAUPDATE] Force service pack hidden"); |
|
1009 // Because service pack is already installed, set |
|
1010 // it as hidden itself. Do not delete it because |
|
1011 // there may be some dependencies set to it before |
|
1012 // from other service packs. By setting node hidden, |
|
1013 // it will not be included into the main list. |
|
1014 node.ForceHidden( ETrue ); |
|
1015 } |
|
1016 |
|
1017 // Nodes of service pack are set to hidden. |
|
1018 // These nodes itself may have dependencies, but they are not forced hidden. |
|
1019 // |
|
1020 node.GetDependencyNodesL( servicePackNodes, ETrue ); |
|
1021 for ( TInt j = 0; j < servicePackNodes.Count(); ++j ) |
|
1022 { |
|
1023 CIAUpdateNode& servicePackNode( *servicePackNodes[ j ] ); |
|
1024 if ( !servicePackNode.IsSelfUpdate() ) |
|
1025 { |
|
1026 servicePackNode.ForceHidden( ETrue ); |
|
1027 } |
|
1028 } |
|
1029 // Reset the array, because we may use the array in |
|
1030 // next loops. |
|
1031 servicePackNodes.Reset(); |
|
1032 } |
|
1033 } |
|
1034 |
|
1035 CleanupStack::PopAndDestroy( &servicePackNodes ); |
|
1036 |
|
1037 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::HandleServicePacksL() end"); |
|
1038 } |
|
1039 |
|
1040 |
|
1041 TBool CIAUpdateNodeContainer::InstallCheckL( CIAUpdateNode& aNode ) const |
|
1042 { |
|
1043 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::InstallCheckL() begin"); |
|
1044 |
|
1045 TBool checkPassed( ETrue ); |
|
1046 |
|
1047 // Notice, that service packs are accepted even if they |
|
1048 // would be already installed. This is because service |
|
1049 // packs themselves contain dependencies and these dependencies |
|
1050 // may not be set yet. So, after all the nodes are available, |
|
1051 // the service packs can be checked separately. |
|
1052 if ( aNode.Type() != MIAUpdateNode::EPackageTypeServicePack ) |
|
1053 { |
|
1054 IAUPDATE_TRACE("[IAUPDATE] Not a service pack"); |
|
1055 |
|
1056 TIAUpdateVersion installedVersion; |
|
1057 TBool installed( |
|
1058 IAUpdateUtils::IsAppInstalledL( aNode.Uid(), installedVersion ) ); |
|
1059 // Notice that here we let the check pass also if node has the same version |
|
1060 // as the installed content. By accepting same version, the dependency chains |
|
1061 // will contain the currently installed node dependency information. Then, |
|
1062 // if newer dependencies are provided for the already installed content, |
|
1063 // they will be handled correctly for example inside service packs. |
|
1064 if ( installed ) |
|
1065 { |
|
1066 IAUPDATE_TRACE("[IAUPDATE] Content installed"); |
|
1067 if ( installedVersion > aNode.Version() ) |
|
1068 { |
|
1069 IAUPDATE_TRACE("[IAUPDATE] Newer version already installed."); |
|
1070 // If the installed version is newer, then think the node as |
|
1071 // installed. |
|
1072 checkPassed = EFalse; |
|
1073 } |
|
1074 else if ( installedVersion == aNode.Version() ) |
|
1075 { |
|
1076 IAUPDATE_TRACE("[IAUPDATE] Force node hidden"); |
|
1077 // Node is already installed but we still want to include |
|
1078 // it into the dependency chain. But, node should not be |
|
1079 // shown in the UI. So, force the installed node as hidden. |
|
1080 aNode.ForceHidden( ETrue ); |
|
1081 } |
|
1082 } |
|
1083 } |
|
1084 |
|
1085 IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateNodeContainer::InstallCheckL() end: %d", |
|
1086 checkPassed); |
|
1087 |
|
1088 return checkPassed; |
|
1089 } |