|
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 * CPackageInfo implementation |
|
16 * |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 #include <e32base.h> |
|
22 #include <f32file.h> |
|
23 #include <sysutil.h> // SysUtil::DiskSpaceBelowCriticalLevel() |
|
24 |
|
25 #include "ADMXmlParser.h" |
|
26 #include "ADMPackageInfo.h" |
|
27 #include "ADMDownloadHandler.h" |
|
28 #include "ADMAppUi.h" |
|
29 |
|
30 #include "macros.h" |
|
31 |
|
32 //TODO: Right place?! |
|
33 // The extension of the changes file |
|
34 _LIT(KChangesExt,"_changes.xml"); |
|
35 |
|
36 CPackageInfo* CPackageInfo::NewLC() |
|
37 { |
|
38 CPackageInfo* object = new ( ELeave ) CPackageInfo(); |
|
39 CleanupStack::PushL( object ); |
|
40 object->ConstructL(); |
|
41 return object; |
|
42 } |
|
43 |
|
44 CPackageInfo* CPackageInfo::NewL() |
|
45 { |
|
46 CPackageInfo* object = CPackageInfo::NewLC(); |
|
47 CleanupStack::Pop(); |
|
48 return object; |
|
49 } |
|
50 |
|
51 void CPackageInfo::ConstructL() |
|
52 { |
|
53 } |
|
54 |
|
55 CPackageInfo::CPackageInfo() : |
|
56 iPackageStatus(EPackageStatusUnknown), |
|
57 iEdgeDlinkHdr(_FOFF(Edge, iEdgeDlink)), |
|
58 iEdgeDlinkIter(iEdgeDlinkHdr) |
|
59 { |
|
60 } |
|
61 |
|
62 CPackageInfo::~CPackageInfo() |
|
63 { |
|
64 Edge* currentitem; |
|
65 |
|
66 iEdgeDlinkIter.SetToFirst(); |
|
67 |
|
68 // Clear the memory allocated for all Edges. |
|
69 while((currentitem = iEdgeDlinkIter++) != NULL) |
|
70 { |
|
71 currentitem->iEdgeDlink.Deque(); |
|
72 delete currentitem; |
|
73 }; |
|
74 |
|
75 DELETE_IF_NONNULL( iPackageName ); |
|
76 DELETE_IF_NONNULL( iVendor ); |
|
77 DELETE_IF_NONNULL( iDateOfSubmission ); |
|
78 DELETE_IF_NONNULL( iDateOfModification ); |
|
79 DELETE_IF_NONNULL( iUrl ); |
|
80 DELETE_IF_NONNULL( iDownloadUrl ); |
|
81 DELETE_IF_NONNULL( iDepFileName ); |
|
82 DELETE_IF_NONNULL( iChangesFileName ); |
|
83 DELETE_IF_NONNULL( iSisPackageName ); |
|
84 } |
|
85 |
|
86 void CPackageInfo::AddEdgeL(CPackageInfo* aDest) |
|
87 { |
|
88 User::LeaveIfNull(aDest); |
|
89 |
|
90 Edge* newEdge = Edge::NewL(this, aDest); |
|
91 if (iEdgeDlinkHdr.IsEmpty()) |
|
92 { |
|
93 // This is the first Edge in the list |
|
94 iEdgeDlinkHdr.AddFirst(*newEdge); |
|
95 iEdgeDlinkIter.SetToFirst(); |
|
96 } |
|
97 else |
|
98 { |
|
99 // Append Edge to the list |
|
100 iEdgeDlinkHdr.AddLast(*newEdge); |
|
101 iEdgeDlinkIter.SetToLast(); |
|
102 } |
|
103 } |
|
104 |
|
105 void CPackageInfo::VisitL(CDepTree *aDepTree) |
|
106 { |
|
107 // TODO: Proper error handling |
|
108 User::LeaveIfNull(aDepTree); |
|
109 |
|
110 Edge *e; |
|
111 CPackageInfo *temp; |
|
112 |
|
113 if (iVisited == BEING_VISITED) |
|
114 { |
|
115 // Cycle is detected |
|
116 aDepTree->iCyclePresent = ETrue; |
|
117 return; |
|
118 } |
|
119 if (iVisited == DONE_VISITED) |
|
120 { |
|
121 // Node already visited added to the fetch list |
|
122 return; |
|
123 } |
|
124 |
|
125 iVisited = BEING_VISITED; |
|
126 |
|
127 // Visit all the Edges first |
|
128 while(iEdgeDlinkIter!= NULL) |
|
129 { |
|
130 e = iEdgeDlinkIter--; |
|
131 temp = e->GetVertexDst(); |
|
132 temp->VisitL(aDepTree); |
|
133 } |
|
134 iVisited = DONE_VISITED; |
|
135 |
|
136 aDepTree->AddFetchPackageInfo(this); |
|
137 } |
|
138 |
|
139 void CPackageInfo::SetDepFileNameL(const TDesC& aName) |
|
140 { |
|
141 __ASSERT_ALWAYS( aName.Length() > 0, User::Leave( KErrArgument) ); |
|
142 |
|
143 DELETE_IF_NONNULL( iDepFileName ); |
|
144 iDepFileName = aName.AllocL(); |
|
145 } |
|
146 |
|
147 //TODO : Clean possible? |
|
148 void CPackageInfo::SetChangesFileNameL() |
|
149 { |
|
150 DELETE_IF_NONNULL( iChangesFileName ); |
|
151 |
|
152 #ifdef FEATURE_CHANGES_USE_UID |
|
153 //By default, use Packageuid as the Changes filename. |
|
154 //set the length as ( PackageUIDLength (8) + Changes_ext length ) |
|
155 iChangesFileName = HBufC::NewL(8 + KChangesExt().Length()); |
|
156 TPtr nameBufPtr = iChangesFileName->Des(); |
|
157 nameBufPtr.Num(GetPackageUid(), EHex); |
|
158 nameBufPtr.Append(KChangesExt); |
|
159 #else |
|
160 //Use Packagename as the Changes filename. |
|
161 // If package name is NULL, then Package UID is used as Changes file name. |
|
162 if( GetPackageName() != NULL ) |
|
163 { |
|
164 iChangesFileName = HBufC::NewL( GetPackageName()->Length() + |
|
165 KChangesExt().Length() ); |
|
166 TPtr nameBufPtr = iChangesFileName->Des(); |
|
167 nameBufPtr.Copy(GetPackageName()->Des()); |
|
168 |
|
169 const TInt nameLength = GetPackageName()->LocateReverse('.'); |
|
170 |
|
171 if (nameLength != KErrNotFound) |
|
172 { |
|
173 //Remove the extension. |
|
174 nameBufPtr.Delete( nameLength, GetPackageName()->Length() - nameLength); |
|
175 } |
|
176 nameBufPtr.Append(KChangesExt); |
|
177 } |
|
178 else |
|
179 { |
|
180 iChangesFileName = HBufC::NewL(8 + KChangesExt().Length()); |
|
181 TPtr nameBufPtr = iChangesFileName->Des(); |
|
182 nameBufPtr.Num(GetPackageUid(), EHex); |
|
183 nameBufPtr.Append(KChangesExt); |
|
184 } |
|
185 #endif |
|
186 } |
|
187 |
|
188 void CPackageInfo::SetSisFileNameL(const TDesC& aName) |
|
189 { |
|
190 __ASSERT_ALWAYS( aName.Length() > 0, User::Leave( KErrArgument) ); |
|
191 |
|
192 DELETE_IF_NONNULL( iSisPackageName ); |
|
193 iSisPackageName = aName.AllocL(); |
|
194 } |
|
195 |
|
196 // ----------------------------------------------------------------------------- |
|
197 // Creates download URL for the package. The constructed URL is stored in |
|
198 // member variable iDownloadUrl. The URL is constructed only once, the |
|
199 // subsequent calls to this return iDownloadUrl. |
|
200 // |
|
201 // base_url/package/version/dep_file |
|
202 // i.e. |
|
203 // http://server.somewhere.net/root/qt/4.6.1/qt_dep.xml |
|
204 // ----------------------------------------------------------------------------- |
|
205 // |
|
206 HBufC8* CPackageInfo::GetDownloadUrlL() |
|
207 { |
|
208 #ifdef FEATURE_CHANGES_DOWNLOAD_URL |
|
209 if (iDownloadUrl) |
|
210 { |
|
211 return iDownloadUrl; |
|
212 } |
|
213 |
|
214 // Url should never be null as specifying |
|
215 // the Url in changes file is mandatory |
|
216 User::LeaveIfNull(iUrl); |
|
217 |
|
218 TInt len = iUrl->Des().Length(); |
|
219 #ifdef FEATURE_CHANGES_USE_UID |
|
220 len += 8; // UID length as HEX string // iPackageName->Length(); |
|
221 #else |
|
222 len += iPackageName->Length(); |
|
223 #endif |
|
224 |
|
225 // TVersion: iMajor(8bit), iMinor(8bit), iBuild(16bit) = 255 255 65535 |
|
226 // delimiters: /qt/4.6.1/ => //../ = (len=5) |
|
227 len += (3+3+5 + 5); |
|
228 |
|
229 HBufC8* url = HBufC8::NewL(len); |
|
230 TPtr8 urlPtr = url->Des(); |
|
231 // Construct the download path: |
|
232 // base_url/package/version/dep_file |
|
233 // i.e. |
|
234 // http://server.somewhere.net/root/qt/4.6.1/qt_dep.xml |
|
235 urlPtr.Copy(*iUrl); |
|
236 |
|
237 // Append forward slash if that's missing |
|
238 if (urlPtr.Right(1)[0] != '/') |
|
239 { |
|
240 urlPtr.Append('/'); |
|
241 } |
|
242 |
|
243 #ifdef FEATURE_CHANGES_USE_UID |
|
244 urlPtr.AppendNum(iPackageUid, EHex); |
|
245 #else |
|
246 urlPtr.Append(iPackageName->Des()); |
|
247 #endif |
|
248 urlPtr.Append('/'); |
|
249 urlPtr.AppendNum(iVersion.iMajor); |
|
250 urlPtr.Append('.'); |
|
251 urlPtr.AppendNum(iVersion.iMinor); |
|
252 urlPtr.Append('.'); |
|
253 urlPtr.AppendNum(iVersion.iBuild); |
|
254 urlPtr.Append('/'); |
|
255 |
|
256 iDownloadUrl = url; |
|
257 |
|
258 return url; |
|
259 #else |
|
260 // Url should never be null as specifying |
|
261 // the Url in changes file is mandatory |
|
262 User::LeaveIfNull(iUrl); |
|
263 return iUrl; |
|
264 #endif // FEATURE_CHANGES_DOWNLOAD_URL |
|
265 } |
|
266 |
|
267 #ifdef USE_LOGFILE |
|
268 CDepTree* CDepTree::NewLC(RFileLogger& aLogger, const TDesC& aDownloadPath) |
|
269 { |
|
270 CDepTree* object = new ( ELeave ) CDepTree(aLogger); |
|
271 #else |
|
272 CDepTree* CDepTree::NewLC(const TDesC& aDownloadPath) |
|
273 { |
|
274 CDepTree* object = new ( ELeave ) CDepTree(); |
|
275 #endif |
|
276 CleanupStack::PushL( object ); |
|
277 object->ConstructL(aDownloadPath); |
|
278 return object; |
|
279 } |
|
280 |
|
281 #ifdef USE_LOGFILE |
|
282 CDepTree* CDepTree::NewL(RFileLogger& aLogger, const TDesC& aDownloadPath) |
|
283 { |
|
284 CDepTree* object = CDepTree::NewLC(aLogger, aDownloadPath); |
|
285 #else |
|
286 CDepTree* CDepTree::NewL(const TDesC& aDownloadPath) |
|
287 { |
|
288 CDepTree* object = CDepTree::NewLC(aDownloadPath); |
|
289 #endif |
|
290 CleanupStack::Pop(); |
|
291 return object; |
|
292 } |
|
293 |
|
294 #ifdef USE_LOGFILE |
|
295 CDepTree::CDepTree(RFileLogger& aLogger) : |
|
296 iLog(aLogger), |
|
297 #else |
|
298 CDepTree::CDepTree() : |
|
299 #endif |
|
300 iCurrentPackage(-1), |
|
301 iSortedPackage(-1), |
|
302 iCyclePresent(EFalse), |
|
303 iPackageDlinkHdr(_FOFF(CPackageInfo,iPackageDlink)), |
|
304 iPackageDlinkFetchIter(iPackageDlinkHdr) |
|
305 { |
|
306 iFetchList.Reset(); |
|
307 iSortedList.Reset(); |
|
308 } |
|
309 |
|
310 void CDepTree::ConstructL(const TDesC& aDownloadPath) |
|
311 { |
|
312 iDownloadPath = aDownloadPath.AllocL(); |
|
313 } |
|
314 |
|
315 CDepTree::~CDepTree() |
|
316 { |
|
317 DELETE_IF_NONNULL( iDownloadPath ); |
|
318 |
|
319 CPackageInfo* currentPackage; |
|
320 iPackageDlinkFetchIter.SetToFirst(); |
|
321 |
|
322 TDblQueIter<CPackageInfo> PackageIter(iPackageDlinkHdr); |
|
323 PackageIter.SetToFirst(); |
|
324 |
|
325 // Clear memory allocated for all packages |
|
326 while((currentPackage = PackageIter++) != NULL) |
|
327 { |
|
328 currentPackage->iPackageDlink.Deque(); |
|
329 delete currentPackage; |
|
330 }; |
|
331 |
|
332 iFetchList.Close(); |
|
333 iSortedList.Close(); |
|
334 } |
|
335 |
|
336 const TLinearOrder<CPackageInfo> CPackageInfo::KSortOrderByDrivePriority(CPackageInfo::CompareByDrivePriority); |
|
337 |
|
338 TInt CPackageInfo::CompareByDrivePriority( const CPackageInfo& aPackageOne, const CPackageInfo& aPackageTwo ) |
|
339 { |
|
340 if ( (aPackageOne.GetDrivePriority()) > (aPackageTwo.GetDrivePriority()) ) |
|
341 { |
|
342 return -1; |
|
343 } |
|
344 else |
|
345 { |
|
346 return 1; |
|
347 } |
|
348 } |
|
349 |
|
350 TBool CDepTree::ConstructFetchListL() |
|
351 { |
|
352 if(iPackageDlinkHdr.IsEmpty()) |
|
353 { |
|
354 return EFalse; |
|
355 } |
|
356 |
|
357 CPackageInfo *rootNode = iPackageDlinkHdr.First(); |
|
358 rootNode->VisitL(this); |
|
359 return ETrue; |
|
360 } |
|
361 |
|
362 TBool CDepTree::SetDriveInfo() |
|
363 { |
|
364 #ifdef FEATURE_INSTALL_DRIVE_SELECTION |
|
365 TInt driveIndex = 0; |
|
366 CPackageInfo* currentNode = NULL; |
|
367 TBool retStatus = ETrue; // Default to successful check |
|
368 RArray<TChar> driveLetters(EDriveZ-EDriveA+1); |
|
369 RArray<TInt64> driveSpaces(EDriveZ-EDriveA+1); |
|
370 RFs fs; |
|
371 |
|
372 if (fs.Connect() != KErrNone) |
|
373 { |
|
374 return EFalse; |
|
375 } |
|
376 |
|
377 CleanupClosePushL(fs); |
|
378 CleanupClosePushL(driveLetters); |
|
379 CleanupClosePushL(driveSpaces); |
|
380 |
|
381 // Get the drive letters and spaces |
|
382 TRAPD(err, GetDriveListL(fs, driveLetters, driveSpaces) ); |
|
383 if (err != KErrNone) |
|
384 { |
|
385 return EFalse; |
|
386 } |
|
387 |
|
388 // The packages are sorted based on priority |
|
389 for (TInt index = 0; (index < iSortedList.Count()) && (retStatus != EFalse); index++ ) |
|
390 { |
|
391 //LOG2( "Index is %d", index ); |
|
392 |
|
393 currentNode = iSortedList[index]; |
|
394 |
|
395 const TChar mandatoryDriveLetter = currentNode->GetMandatoryInstallDrive(); |
|
396 |
|
397 if ( mandatoryDriveLetter ) |
|
398 { |
|
399 // Reset the driveIndex for drive selection of each package. |
|
400 for ( driveIndex = 0; driveIndex < driveSpaces.Count(); driveIndex++ ) |
|
401 { |
|
402 // Check whether the current drive is the mandatory drive. |
|
403 if ( driveLetters[driveIndex] == mandatoryDriveLetter ) |
|
404 { |
|
405 // Check whether there is enough space in mandatory drive. |
|
406 if ( currentNode->GetInstallSize() < driveSpaces[driveIndex] ) |
|
407 { |
|
408 LOG3( "PkgUid 0x%08X installation forced to %c:", currentNode->GetPackageUid(), (char)driveLetters[driveIndex] ); |
|
409 currentNode->SetInstallDrive(driveLetters[driveIndex]); |
|
410 driveSpaces[driveIndex] -= currentNode->GetInstallSize(); |
|
411 } |
|
412 else |
|
413 { |
|
414 retStatus = EFalse; |
|
415 } |
|
416 break; |
|
417 } |
|
418 } |
|
419 }// if ( mandatoryDriveLetter ) |
|
420 else |
|
421 { |
|
422 // driveIndex is reset -> there could be a smaller package which fits in previous drive. |
|
423 for ( driveIndex = 0; driveIndex < driveSpaces.Count(); driveIndex++ ) |
|
424 { |
|
425 if (currentNode->GetInstallSize() < driveSpaces[driveIndex]) |
|
426 { |
|
427 currentNode->SetInstallDrive(driveLetters[driveIndex]); |
|
428 driveSpaces[driveIndex] -= currentNode->GetInstallSize(); |
|
429 break; |
|
430 } |
|
431 } |
|
432 }// else of if ( mandatoryDriveLetter ) |
|
433 |
|
434 if ( driveSpaces.Count() <= driveIndex ) |
|
435 { |
|
436 //Invalid mandatory drive specified. |
|
437 retStatus = EFalse; |
|
438 } |
|
439 }// for loop of packages |
|
440 |
|
441 // All the dependent sis files are assigned the drives where they need to be installed. |
|
442 // Now go thru the drives to figure out which one can accommodate the download. |
|
443 |
|
444 // This is done as a final act so that the memory is not blocked unnecessarily by download, |
|
445 // which otherwise could be used to install a dependency sis. |
|
446 |
|
447 // Reset the driveIndex -> start from system drive. |
|
448 for ( driveIndex = 0; ( driveIndex < driveSpaces.Count() ) && ( retStatus != EFalse ); driveIndex++ ) |
|
449 { |
|
450 /* |
|
451 TInt drive; |
|
452 RFs::CharToDrive(driveLetters[driveIndex], drive); |
|
453 if (!SysUtil::DiskSpaceBelowCriticalLevelL(&fs, iMaxDownloadSize, drive)) |
|
454 { |
|
455 */ |
|
456 if ( driveSpaces[driveIndex] > iMaxDownloadSize ) |
|
457 { |
|
458 driveSpaces[driveIndex] -= iMaxDownloadSize; |
|
459 iDownloadDrive = driveLetters[driveIndex]; |
|
460 //Drive specified in download path is overriden. |
|
461 iDownloadPath->Des()[0] = iDownloadDrive; |
|
462 LOG4( "Download drive %c: free %ld (%.02f MB)", (char)iDownloadDrive, driveSpaces[driveIndex], (TReal)driveSpaces[driveIndex]/1048576.0 ); |
|
463 break; |
|
464 } |
|
465 } |
|
466 |
|
467 // Fail, if no drive has space to max download size. |
|
468 if ( driveSpaces.Count() <= driveIndex ) |
|
469 { |
|
470 // Fail: no memory. |
|
471 retStatus = EFalse; |
|
472 } |
|
473 |
|
474 CleanupStack::PopAndDestroy(3, &fs); |
|
475 |
|
476 return retStatus; |
|
477 |
|
478 #else |
|
479 TInt64 driveSpace = iMaxDownloadSize; |
|
480 CPackageInfo* currentNode = NULL; |
|
481 const TInt installDrive = RFs::GetSystemDrive(); |
|
482 TChar instDriveLetter; |
|
483 TInt err; |
|
484 TBool retStatus = ETrue; // Default to successful check |
|
485 RFs fs; |
|
486 |
|
487 err = fs.Connect(); |
|
488 if (err != KErrNone) |
|
489 return EFalse; |
|
490 |
|
491 CleanupClosePushL(fs); |
|
492 |
|
493 RFs::DriveToChar(installDrive, instDriveLetter); |
|
494 |
|
495 // The install size of all dependent packages to be installed is added to the required driveSpace. |
|
496 for (TInt index = 0; index < iSortedList.Count(); index++ ) |
|
497 { |
|
498 currentNode = iSortedList[index]; |
|
499 driveSpace += currentNode->GetInstallSize(); |
|
500 // Set the installation drive for the package |
|
501 currentNode->SetInstallDrive(instDriveLetter); |
|
502 } |
|
503 |
|
504 // check whether there is enough space in C to download and install all dependencies. |
|
505 TRAP( err, retStatus = !SysUtil::DiskSpaceBelowCriticalLevelL( &fs, driveSpace, installDrive ) ); |
|
506 |
|
507 // If free space check fails, indicate not enough space |
|
508 if (err != KErrNone) |
|
509 retStatus = EFalse; |
|
510 |
|
511 CleanupStack::PopAndDestroy(&fs); |
|
512 |
|
513 return retStatus; |
|
514 #endif |
|
515 } |
|
516 |
|
517 void CDepTree::GetDriveListL(RFs& aRFs, RArray<TChar>& aDriveLetters, RArray<TInt64>& aDriveSpaces) |
|
518 { |
|
519 // This is the LFSS free space threshold |
|
520 const TInt freeSpaceAdjustment = 1024 * 384; |
|
521 |
|
522 // get information about drives |
|
523 TDriveList driveList; |
|
524 |
|
525 // List all drives in the system |
|
526 User::LeaveIfError( aRFs.DriveList(driveList) ); |
|
527 |
|
528 TVolumeInfo volInfo; |
|
529 TInt64 volSpace = 0; |
|
530 TChar systemDriveLetter; |
|
531 const TInt systemDrive = RFs::GetSystemDrive(); |
|
532 |
|
533 // Not sure whether the first DriveLetter in the while loop corresponds to SystemDrive. |
|
534 // Hence setting it explicitly as the first entry in Drive Array |
|
535 RFs::DriveToChar(systemDrive, systemDriveLetter); |
|
536 if (aRFs.Volume(volInfo, systemDrive) == KErrNone) |
|
537 { |
|
538 LOG4( "SysDrive %c: Free %ld (%.02f MB)", (char)systemDriveLetter, volInfo.iFree, (TReal)volInfo.iFree/1048576.0 ); |
|
539 volSpace = volInfo.iFree - freeSpaceAdjustment; // bytes |
|
540 if (volSpace < 0) |
|
541 { |
|
542 volSpace = 0; |
|
543 } |
|
544 } |
|
545 |
|
546 User::LeaveIfError(aDriveLetters.Append(systemDriveLetter)); |
|
547 User::LeaveIfError(aDriveSpaces.Append(volSpace)); |
|
548 |
|
549 // Check all drives |
|
550 for (TInt driveNumber = EDriveA; driveNumber <= EDriveZ; driveNumber++) |
|
551 { |
|
552 |
|
553 if (!driveList[driveNumber]) |
|
554 { |
|
555 // Not a recognised drive |
|
556 continue; |
|
557 } |
|
558 |
|
559 if (aRFs.Volume(volInfo, driveNumber) != KErrNone) |
|
560 { |
|
561 // The volume is not usable (e.g. no media card inserted) |
|
562 continue; |
|
563 } |
|
564 |
|
565 if (driveNumber == systemDrive) |
|
566 { |
|
567 //System Drive, already added to the list |
|
568 continue; |
|
569 } |
|
570 |
|
571 if ( (volInfo.iDrive.iType==EMediaNotPresent) || |
|
572 (volInfo.iDrive.iType==EMediaRom) || |
|
573 (volInfo.iDrive.iType==EMediaRemote) || |
|
574 (volInfo.iDrive.iType==EMediaRam) || |
|
575 (volInfo.iDrive.iType==EMediaUnknown) ) |
|
576 { |
|
577 // Exclude drives not suitable for installation |
|
578 continue; |
|
579 } |
|
580 |
|
581 // Do not list read only and substituted drives as an option to install to |
|
582 if (volInfo.iDrive.iDriveAtt & KDriveAttRom || |
|
583 volInfo.iDrive.iDriveAtt & KDriveAttSubsted) |
|
584 { |
|
585 continue; |
|
586 } |
|
587 |
|
588 const TInt64 volSpace = volInfo.iFree - freeSpaceAdjustment; // bytes |
|
589 if (volSpace < 0) |
|
590 { |
|
591 // Volume space below 0 => skip drive |
|
592 continue; |
|
593 } |
|
594 |
|
595 TChar drvLetter; |
|
596 User::LeaveIfError(RFs::DriveToChar(driveNumber, drvLetter)); |
|
597 User::LeaveIfError(aDriveLetters.Append(drvLetter)); |
|
598 User::LeaveIfError(aDriveSpaces.Append(volSpace)); |
|
599 LOG4( "Drive %c: Free %ld (%.02f MB)", (char)drvLetter, volSpace, (TReal)volSpace/1048576.0 ); |
|
600 } // for |
|
601 } |
|
602 |
|
603 TBool CDepTree::IsDepTreeEmpty() const |
|
604 { |
|
605 return (iPackageDlinkHdr.IsEmpty()); |
|
606 } |
|
607 |
|
608 TBool CDepTree::IsCyclePresent() const |
|
609 { |
|
610 return iCyclePresent; |
|
611 } |
|
612 |
|
613 void CDepTree::AddPackageInfo(CPackageInfo *aPackageInfo) |
|
614 { |
|
615 if(iPackageDlinkHdr.IsEmpty()) |
|
616 { |
|
617 // This is the first node in the list |
|
618 iPackageDlinkHdr.AddFirst(*aPackageInfo); |
|
619 iPackageDlinkFetchIter.SetToFirst(); |
|
620 } |
|
621 else |
|
622 { |
|
623 // Append node to the list |
|
624 iPackageDlinkHdr.AddLast(*aPackageInfo); |
|
625 } |
|
626 } |
|
627 |
|
628 TPtrC CDepTree::GetDownloadPath() const |
|
629 { |
|
630 return iDownloadPath->Des(); |
|
631 } |
|
632 |
|
633 void CDepTree::AddFetchPackageInfo(CPackageInfo *aPackageInfo) |
|
634 { |
|
635 iFetchList.Append(aPackageInfo); |
|
636 //Add the download/install sizes only if the package is not already installed. |
|
637 if(aPackageInfo->iPackageStatus != EPackageInstalled) |
|
638 { |
|
639 iSortedList.InsertInOrder(aPackageInfo,CPackageInfo::KSortOrderByDrivePriority); |
|
640 iTotalDownloadSize += aPackageInfo->iDownloadSize; |
|
641 |
|
642 if(aPackageInfo->iDownloadSize > iMaxDownloadSize) |
|
643 { |
|
644 iMaxDownloadSize = aPackageInfo->iDownloadSize; |
|
645 } |
|
646 } |
|
647 } |
|
648 |
|
649 CPackageInfo* CDepTree::LocatePackageInDepTree(const TUint32& aDepPackageUid) |
|
650 { |
|
651 CPackageInfo* currentItem; |
|
652 TDblQueIter<CPackageInfo> PackageIter(iPackageDlinkHdr); |
|
653 PackageIter.SetToFirst(); |
|
654 |
|
655 while((currentItem = PackageIter++) != NULL) |
|
656 { |
|
657 if(currentItem->iPackageUid == aDepPackageUid) |
|
658 { |
|
659 return currentItem; |
|
660 } |
|
661 }; |
|
662 return NULL; |
|
663 } |
|
664 |
|
665 CPackageInfo* CDepTree::GetNextNode() |
|
666 { |
|
667 CPackageInfo* nextNode; |
|
668 |
|
669 if(iPackageDlinkFetchIter++ != NULL) |
|
670 { |
|
671 // This is because the first node is the root package and |
|
672 // tree is already created from it. |
|
673 nextNode = iPackageDlinkFetchIter; |
|
674 } |
|
675 else |
|
676 { |
|
677 // This case should never arise, as the api |
|
678 // should not get called. |
|
679 nextNode = NULL; |
|
680 } |
|
681 return nextNode; |
|
682 } |
|
683 |
|
684 CPackageInfo* CDepTree::GetFetchNode( TInt nodeLocation) |
|
685 { |
|
686 CPackageInfo* node = NULL; |
|
687 |
|
688 if (iFetchList.Count() > nodeLocation ) |
|
689 { |
|
690 node = iFetchList[nodeLocation]; |
|
691 } |
|
692 return node; |
|
693 } |
|
694 |
|
695 |
|
696 CPackageInfo* CDepTree::GetNextFetchNode() |
|
697 { |
|
698 CPackageInfo* nextNode = NULL; |
|
699 |
|
700 if (iFetchList.Count() > (iCurrentPackage+1) ) |
|
701 { |
|
702 nextNode = iFetchList[++iCurrentPackage]; |
|
703 } |
|
704 return nextNode; |
|
705 } |
|
706 |
|
707 //TODO: Remove this. this is only for testing purpose. |
|
708 //otherwise, there is never a need to get the sorted nodes separately. |
|
709 CPackageInfo* CDepTree::GetNextSortedNode() |
|
710 { |
|
711 CPackageInfo* nextNode = NULL; |
|
712 |
|
713 if (iSortedList.Count() > (iSortedPackage+1) ) |
|
714 { |
|
715 nextNode = iSortedList[++iSortedPackage]; |
|
716 } |
|
717 return nextNode; |
|
718 } |
|
719 |
|
720 CPackageInfo* CDepTree::GetPreviousFetchNode() |
|
721 { |
|
722 CPackageInfo* previousNode = NULL; |
|
723 if (iCurrentPackage > 0) |
|
724 { |
|
725 previousNode = iFetchList[--iCurrentPackage]; |
|
726 } |
|
727 return previousNode; |
|
728 } |
|
729 |
|
730 void CDepTree::RemoveDownloadedFiles(RFs& aRfs) |
|
731 { |
|
732 CPackageInfo* currentItem; |
|
733 TDblQueIter<CPackageInfo> PackageIter(iPackageDlinkHdr); |
|
734 PackageIter.SetToFirst(); |
|
735 |
|
736 // Remove all the downloaded dep and changes file |
|
737 while((currentItem = PackageIter) != NULL) |
|
738 { |
|
739 if ( currentItem->iDepFileName ) |
|
740 { |
|
741 DeleteFile(aRfs, *(currentItem->iDepFileName), *iDownloadPath); |
|
742 } |
|
743 if ( currentItem->iChangesFileName ) |
|
744 { |
|
745 DeleteFile(aRfs, *(currentItem->iChangesFileName), *iDownloadPath); |
|
746 } |
|
747 if ( currentItem->iSisPackageName ) |
|
748 { |
|
749 DeleteFile(aRfs, *(currentItem->iSisPackageName), *iDownloadPath); |
|
750 } |
|
751 PackageIter++; |
|
752 } |
|
753 } |
|
754 |
|
755 void CDepTree::DeleteFile(RFs& aRfs, const TDesC& aFileName, const TDesC& aFilePath ) |
|
756 { |
|
757 TFileName filename; |
|
758 |
|
759 filename.Copy(aFilePath); |
|
760 filename.Append(aFileName); |
|
761 aRfs.Delete(filename); |
|
762 } |
|
763 |
|
764 CPackageInfo* CDepTree::GetRootNode() |
|
765 { |
|
766 if (iPackageDlinkHdr.IsEmpty()) |
|
767 { |
|
768 return NULL; |
|
769 } |
|
770 else |
|
771 { |
|
772 return iPackageDlinkHdr.First(); |
|
773 } |
|
774 } |
|
775 |
|
776 Edge* Edge::NewLC(CPackageInfo *aVtx1, CPackageInfo *aVtx2) |
|
777 { |
|
778 Edge* object = new ( ELeave ) Edge(aVtx1, aVtx2); |
|
779 CleanupStack::PushL( object ); |
|
780 object->ConstructL(); |
|
781 return object; |
|
782 } |
|
783 |
|
784 Edge* Edge::NewL(CPackageInfo *aVtx1, CPackageInfo *aVtx2) |
|
785 { |
|
786 Edge* object = Edge::NewLC(aVtx1, aVtx2); |
|
787 CleanupStack::Pop(); |
|
788 return object; |
|
789 } |
|
790 |
|
791 void Edge::ConstructL() |
|
792 { |
|
793 } |
|
794 |
|
795 Edge::Edge(CPackageInfo *aVtx1, CPackageInfo *aVtx2) |
|
796 { |
|
797 iVertexOrg = aVtx1; |
|
798 iVertexDst = aVtx2; |
|
799 } |
|
800 |
|
801 CPackageInfo* Edge::GetVertexOrg() const |
|
802 { |
|
803 return iVertexOrg; |
|
804 } |
|
805 |
|
806 CPackageInfo* Edge::GetVertexDst() const |
|
807 { |
|
808 return iVertexDst; |
|
809 } |