|
1 // Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Implements backup and restore support for the Bluetooth Manager server. |
|
15 // |
|
16 |
|
17 #include <e32std.h> |
|
18 #include <e32base.h> |
|
19 #include <e32property.h> |
|
20 #include <f32file.h> |
|
21 #include <s32file.h> |
|
22 #include "btmanserverutil.h" |
|
23 #include "btmanserverburmgr.h" |
|
24 #include "BTManServer.h" |
|
25 |
|
26 #include "btmanclient.h" |
|
27 #include "btdevice.h" |
|
28 #include <bluetooth/hci/hcitypes.h> |
|
29 #include <bluetooth/logger.h> |
|
30 #include "BTSec.h" |
|
31 |
|
32 #ifdef __FLOG_ACTIVE |
|
33 _LIT8(KLogComponent, LOG_COMPONENT_BT_MANAGER_SERVER); |
|
34 #endif |
|
35 |
|
36 |
|
37 /** |
|
38 Raises an EBTBURMgrInvalidState panic with state information encoded within the panic code. |
|
39 The first digit denotes the panic code (EBTBURMgrInvalidState). |
|
40 The second digit is a delimiter and is always 1. |
|
41 The next two digits represent the expected state |
|
42 The next digit again is a delimiter and is always 1. |
|
43 The final two digits represent the actual state. |
|
44 |
|
45 For example, the panic code 7101100 indicates an EBTBURMgrInvalidState panic raised because the state |
|
46 machine is in the EBTBURStateNormal state when it was expected to be in the EBTBURStateBackupRequest state. |
|
47 **/ |
|
48 void InvalidStatePanic(TBTBURState aExpectedState, TBTBURState aActualState) |
|
49 { |
|
50 LOG_STATIC_FUNC |
|
51 User::Panic(KBTBackupPanicCat, (EBTBURMgrInvalidState*KBTBackupStatePanicMultiplier) + KBTBackupStatePanicMajorDelimiter + (aExpectedState * KBTBackupStateMultiplier) + KBTBackupStatePanicMinorDelimiter + aActualState); |
|
52 } |
|
53 |
|
54 /** |
|
55 Raises an EBTBURMgrInvalidStateTransition panic with state information encoded within the panic code. |
|
56 The first digit denotes the panic code (EBTBURMgrInvalidStateTransition). |
|
57 The second digit is a delimiter and is always 1. |
|
58 The next two digits represent the expected state |
|
59 The next digit again is a delimiter and is always 1. |
|
60 The final two digits represent the actual state. |
|
61 |
|
62 For example, the panic code 6101100 indicates an EBTBURMgrInvalidStateTransition panic raised because the state |
|
63 machine is in the EBTBURStateNormal state when it was expected to be in the EBTBURStateBackupRequest state. |
|
64 **/ |
|
65 void InvalidStateTransitionPanic(TBTBURState aCurrentState, TBTBUREvent aEvent) |
|
66 { |
|
67 LOG_STATIC_FUNC |
|
68 User::Panic(KBTBackupPanicCat, (EBTBURMgrInvalidStateTransition*KBTBackupStatePanicMultiplier) + KBTBackupStatePanicMajorDelimiter + (aCurrentState * KBTBackupStateMultiplier) + KBTBackupStatePanicMinorDelimiter + aEvent); |
|
69 } |
|
70 |
|
71 |
|
72 /** |
|
73 CBTManServerBURMgr - Manages backup and restore support for the Bluetooth Manager server. |
|
74 **/ |
|
75 |
|
76 /** |
|
77 Constructs a new instance of a CBTManServerBURMgr. |
|
78 An MBTBURNotify instance may be registered here for notifications. Ownership of the MBTBURNotify instance is not transferred. |
|
79 @see CBTManServerBURMgr::RequestBURNotification() |
|
80 **/ |
|
81 CBTManServerBURMgr* CBTManServerBURMgr::NewL(CBTManServer& aBTManServer, MBTBURNotify* aBURNotify, TInt aPriority) |
|
82 { |
|
83 LOG_STATIC_FUNC |
|
84 CBTManServerBURMgr* self = new(ELeave) CBTManServerBURMgr(aBTManServer, aBURNotify, aPriority); |
|
85 CleanupStack::PushL(self); |
|
86 self->ConstructL(); |
|
87 CleanupStack::Pop(self); |
|
88 return self; |
|
89 } |
|
90 |
|
91 CBTManServerBURMgr::CBTManServerBURMgr(CBTManServer& aBTManServer, MBTBURNotify* aBURNotify, TInt aPriority) |
|
92 : CActive(aPriority), |
|
93 iBTManServer(aBTManServer), |
|
94 iBUROperationStartNotified(EFalse) |
|
95 { |
|
96 LOG_FUNC |
|
97 |
|
98 RequestBURNotification(aBURNotify); |
|
99 CActiveScheduler::Add(this); |
|
100 } |
|
101 |
|
102 CBTManServerBURMgr::~CBTManServerBURMgr() |
|
103 { |
|
104 LOG_FUNC |
|
105 |
|
106 Cancel(); |
|
107 iProperty.Close(); |
|
108 |
|
109 // Close any open session on BT Manager |
|
110 NotifyAnyBUROperationStopped(); |
|
111 |
|
112 // Members which either hold data or are NULL |
|
113 delete iActiveBackupClient; |
|
114 delete iActiveBackupDataClient; |
|
115 delete iBackupHandler; |
|
116 delete iRestoreHandler; |
|
117 delete iLocalAddrFetcher; |
|
118 |
|
119 // Member that is instantiated for entire lifetime of CBTManServerBURMgr |
|
120 delete iStateMachine; |
|
121 } |
|
122 |
|
123 void CBTManServerBURMgr::ConstructL() |
|
124 { |
|
125 LOG_FUNC |
|
126 |
|
127 // Construct state machine |
|
128 iStateMachine = CBTManServerBURMgrStateFactory::NewL(*this); |
|
129 // Construction counts as a transition into the default state (EBTBURStateNormal) of the state machine. |
|
130 // However, since this does nothing if no backup/restore cleanup is required, we do not need to execute the |
|
131 // state action. |
|
132 |
|
133 // Setup iProperty to catch BUR flag from Secure Backup Engine |
|
134 LEAVEIFERRORL(iProperty.Attach(KUidSystemCategory, KUidBackupRestoreKey)); |
|
135 |
|
136 // Subscribe to BUR P&S key to catch transitions |
|
137 SubscribeToBackupRestoreKey(); |
|
138 |
|
139 // Also check flag now (it may have already transitioned) |
|
140 TInt backupKeyValue = 0; |
|
141 LEAVEIFERRORL(iProperty.Get(backupKeyValue)); |
|
142 TBURPartType backupState = GetBURPartType(backupKeyValue); |
|
143 |
|
144 // If we're not about to perform a restore, check if a restore file exists. If so, try to process restore file. |
|
145 // The restore operation may not affect us, or may be postponed. In either case, we try to process the restore file |
|
146 // again next time we start. |
|
147 if (backupState != EBURRestoreFull && backupState != EBURRestorePartial) |
|
148 { |
|
149 // Delete any stale backup files |
|
150 DeleteBackupFile(); |
|
151 // See if a restore file needs processing |
|
152 CheckForRestoreFileL(); |
|
153 } |
|
154 |
|
155 // Process flag |
|
156 ProcessBackupState(backupState); |
|
157 } |
|
158 |
|
159 /** |
|
160 Translates a given integer obtained from the KUidBackupRestoreKey P&S key to a TBURPartType value. |
|
161 This will validate the masked value to ensure that it falls within the range of the TBURPartType enum. |
|
162 In debug builds, a panic will be raised if this value is out of range. |
|
163 In release builds, EBURUnset is returned if the value is out of range. |
|
164 **/ |
|
165 TBURPartType CBTManServerBURMgr::GetBURPartType(TInt aValue) |
|
166 { |
|
167 LOG_FUNC |
|
168 |
|
169 switch (aValue & KBURPartTypeMask) |
|
170 { |
|
171 case EBURUnset: |
|
172 return EBURUnset; |
|
173 case EBURNormal: |
|
174 return EBURNormal; |
|
175 case EBURBackupFull: |
|
176 return EBURBackupFull; |
|
177 case EBURBackupPartial: |
|
178 return EBURBackupPartial; |
|
179 case EBURRestoreFull: |
|
180 return EBURRestoreFull; |
|
181 case EBURRestorePartial: |
|
182 return EBURRestorePartial; |
|
183 default: |
|
184 __ASSERT_DEBUG(EFalse, PANIC(KBTBackupPanicCat, EBTBURMgrInvalidBackupRestoreState)); |
|
185 return EBURUnset; |
|
186 } |
|
187 } |
|
188 |
|
189 /** |
|
190 Attempts to locate a restore file in the private directory of this server. |
|
191 @return ETrue if the file can be found, EFalse otherwise. |
|
192 **/ |
|
193 TBool CBTManServerBURMgr::RestoreFilePresent() |
|
194 { |
|
195 LOG_FUNC |
|
196 |
|
197 RFs fsSession; |
|
198 TInt err = fsSession.Connect(); |
|
199 if (err == KErrNone) |
|
200 { |
|
201 err = fsSession.SetSessionToPrivate(fsSession.GetSystemDrive()); |
|
202 if (err ==KErrNone) |
|
203 { |
|
204 TEntry entry; |
|
205 err = fsSession.Entry(KBTManServerRestoreFileName, entry); |
|
206 } |
|
207 |
|
208 fsSession.Close(); |
|
209 } |
|
210 |
|
211 // If restore file was found, err will be KErrNone |
|
212 return (err == KErrNone); |
|
213 } |
|
214 |
|
215 /** |
|
216 Checks for the existence of a restore file. If a restore file is found, then the local device address |
|
217 is feteched and processing of that restore file is initiated. |
|
218 **/ |
|
219 void CBTManServerBURMgr::CheckForRestoreFileL() |
|
220 { |
|
221 LOG_FUNC |
|
222 |
|
223 if (RestoreFilePresent()) |
|
224 { |
|
225 // Fetch local address. When this is received, restore file processing will begin. |
|
226 iLocalAddrFetcher = CBTLocalAddressFetcher::NewL(*this, iBTManServer.Registry()); |
|
227 iLocalAddrFetcher->FetchLocalAddress(); |
|
228 } |
|
229 } |
|
230 |
|
231 /** |
|
232 Subscribes to the P&S flag provided by the Secure Backup Engine (to receive notification of backup/restore state changes). |
|
233 **/ |
|
234 void CBTManServerBURMgr::SubscribeToBackupRestoreKey() |
|
235 { |
|
236 LOG_FUNC |
|
237 |
|
238 iProperty.Subscribe(iStatus); |
|
239 SetActive(); |
|
240 } |
|
241 |
|
242 /** |
|
243 Processes a change in the backup/restore state of the device. |
|
244 @param aBackupStateValue A value expressing the backup/restore state of the device. |
|
245 **/ |
|
246 void CBTManServerBURMgr::ProcessBackupState(TBURPartType aBURStateValue) |
|
247 { |
|
248 LOG_FUNC |
|
249 |
|
250 iBURState = aBURStateValue; |
|
251 |
|
252 switch (aBURStateValue) |
|
253 { |
|
254 case EBURBackupFull: |
|
255 // Fall-through |
|
256 case EBURBackupPartial: |
|
257 iStateMachine->TransitionState(EBTBUREventBackup); |
|
258 break; |
|
259 case EBURRestoreFull: |
|
260 // Fall-through |
|
261 case EBURRestorePartial: |
|
262 iStateMachine->TransitionState(EBTBUREventRestore); |
|
263 break; |
|
264 case EBURNormal: |
|
265 iStateMachine->TransitionState(EBTBUREventNormal); |
|
266 break; |
|
267 default: // EBURUnset |
|
268 __ASSERT_DEBUG(aBURStateValue == EBURUnset, PANIC(KBTBackupPanicCat, EBTBURMgrUnknownBUREvent)); |
|
269 iStateMachine->TransitionState(EBTBUREventUnset); |
|
270 } |
|
271 } |
|
272 |
|
273 /** |
|
274 Registers an MBTBURNotify instance to receive notification of backup/restore operations starting and stopping. |
|
275 Ownership of this MBTBURNotify instance is not transferred. |
|
276 Any previous MBTBURNotify instance is deregistered on this method call. |
|
277 Supplying a NULL pointer will deregister the previously registered instance (if present). |
|
278 **/ |
|
279 void CBTManServerBURMgr::RequestBURNotification(MBTBURNotify* aBURNotify) |
|
280 { |
|
281 LOG_FUNC |
|
282 |
|
283 iBURNotify = aBURNotify; |
|
284 } |
|
285 |
|
286 |
|
287 /** |
|
288 Receives a local address from a CBTLocalAddressFetcher instance. |
|
289 This will trigger processing of a pending restore file. |
|
290 **/ |
|
291 void CBTManServerBURMgr::SetLocalAddress(TBTDevAddr& aLocalAddr) |
|
292 { |
|
293 LOG_FUNC |
|
294 __ASSERT_DEBUG(aLocalAddr != TBTDevAddr(), PANIC(KBTBackupPanicCat, EBTBURMgrMissingLocalAddress)); |
|
295 |
|
296 // Use address only if it is non-zero. |
|
297 if (aLocalAddr != TBTDevAddr()) |
|
298 { |
|
299 // Take a copy |
|
300 iLocalAddr = aLocalAddr; |
|
301 // Attempt to start restore file processing. |
|
302 // Note that this will fail if we are not in the normal state. |
|
303 iStateMachine->TransitionState(EBTBUREventProcessRestoreFile); |
|
304 } |
|
305 } |
|
306 |
|
307 /** |
|
308 Receives notification that a restore file has been provided by the Secure Backup Engine. |
|
309 Upon receiving this notification, the restore file is renamed to have the appropriate extension and |
|
310 the local device name is updated in the registry. The restore of the remote devices table is postponed |
|
311 until the next time BTManServer starts, so any ongoing BT connections are not affected. |
|
312 **/ |
|
313 void CBTManServerBURMgr::RestoreFileReady() |
|
314 { |
|
315 LOG_FUNC |
|
316 __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreOngoing, InvalidStatePanic(EBTBURStateRestoreOngoing, iStateMachine->GetCurrentState())); |
|
317 |
|
318 // Rename restore file |
|
319 RenameBackupFileForRestore(); |
|
320 // Attempt to update local device name in the registry (best efforts only) |
|
321 TRAP_IGNORE(UpdateLocalDeviceNameL()); |
|
322 } |
|
323 |
|
324 void CBTManServerBURMgr::HandleStateNormal() |
|
325 { |
|
326 LOG_FUNC |
|
327 __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateNormal, InvalidStatePanic(EBTBURStateNormal, iStateMachine->GetCurrentState())); |
|
328 |
|
329 if (iActiveBackupClient) |
|
330 { |
|
331 // Backup or restore finished |
|
332 if (iBackupHandler) |
|
333 { |
|
334 // Backup operation finished |
|
335 // Delete backup file and destroy backup handler |
|
336 DeleteBackupFile(); |
|
337 delete iBackupHandler; |
|
338 iBackupHandler = NULL; |
|
339 } |
|
340 else |
|
341 { |
|
342 // Restore operation finished |
|
343 delete iActiveBackupDataClient; |
|
344 iActiveBackupDataClient = NULL; |
|
345 } |
|
346 |
|
347 // Destroy active backup client |
|
348 delete iActiveBackupClient; |
|
349 iActiveBackupClient = NULL; |
|
350 |
|
351 // Notify that backup/restore operation has finished |
|
352 NotifyBUROperationStopped(); |
|
353 } |
|
354 } |
|
355 |
|
356 /** |
|
357 Determines if a BUR operation affects the Bluetooth Manager server. |
|
358 @return ETrue if a full backup or restore is ongoing, otherwise the return value |
|
359 given by CActiveBackupClient::DoesPartialBURAffectMeL() |
|
360 **/ |
|
361 TBool CBTManServerBURMgr::DoesBURAffectMeL(CActiveBackupClient& aClient) |
|
362 { |
|
363 LOG_FUNC |
|
364 |
|
365 if (iBURState == EBURBackupFull || iBURState == EBURRestoreFull) |
|
366 { |
|
367 return ETrue; |
|
368 } |
|
369 else |
|
370 { |
|
371 return aClient.DoesPartialBURAffectMeL(); |
|
372 } |
|
373 } |
|
374 |
|
375 void CBTManServerBURMgr::HandleStateBackupRequestL() |
|
376 { |
|
377 LOG_FUNC |
|
378 __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupRequest, InvalidStatePanic(EBTBURStateBackupRequest, iStateMachine->GetCurrentState())); |
|
379 |
|
380 // Determine if this backup operation affects us and transition to next state based on this outcome. |
|
381 iActiveBackupClient = CActiveBackupClient::NewL(); |
|
382 |
|
383 if (DoesBURAffectMeL(*iActiveBackupClient)) |
|
384 { |
|
385 // We're affected, proceed with backup |
|
386 iStateMachine->TransitionState(EBTBUREventBackupProceed); |
|
387 } |
|
388 else |
|
389 { |
|
390 // We're not effected, don't do any backup handling |
|
391 iStateMachine->TransitionState(EBTBUREventBackupReject); |
|
392 } |
|
393 } |
|
394 |
|
395 void CBTManServerBURMgr::HandleStateBackupRequestError() |
|
396 { |
|
397 LOG_FUNC |
|
398 __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupRequest, InvalidStatePanic(EBTBURStateBackupRequest, iStateMachine->GetCurrentState())); |
|
399 |
|
400 // Transition to normal state |
|
401 iStateMachine->TransitionState(EBTBUREventAbortStateAction); |
|
402 } |
|
403 |
|
404 void CBTManServerBURMgr::HandleStateBackupOngoingL() |
|
405 { |
|
406 LOG_FUNC |
|
407 __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupOngoing, InvalidStatePanic(EBTBURStateBackupOngoing, iStateMachine->GetCurrentState())); |
|
408 __ASSERT_DEBUG(iActiveBackupClient, PANIC(KBTBackupPanicCat, EBTBURMgrActiveBackupClientNull)); |
|
409 |
|
410 // Provide notification that a BUR operation has started. |
|
411 NotifyBUROperationStarted(); |
|
412 |
|
413 // Construct backup handler and prepare for backup |
|
414 iBackupHandler = CBTBackupHandler::NewL(*this, iBTManServer.Registry()); |
|
415 iBackupHandler->CreateBackupFileL(); |
|
416 |
|
417 // Signal that we're ready for (passive) backup of prepared file |
|
418 iActiveBackupClient->ConfirmReadyForBURL(KErrNone); |
|
419 |
|
420 // Next state transition will be invoked when BUR P&S key changes |
|
421 } |
|
422 |
|
423 void CBTManServerBURMgr::HandleStateBackupOngoingError() |
|
424 { |
|
425 LOG_FUNC |
|
426 __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupOngoing, InvalidStatePanic(EBTBURStateBackupOngoing, iStateMachine->GetCurrentState())); |
|
427 |
|
428 // Transition to normal state |
|
429 iStateMachine->TransitionState(EBTBUREventAbortStateAction); |
|
430 } |
|
431 |
|
432 void CBTManServerBURMgr::HandleStateBackupIgnore() |
|
433 { |
|
434 LOG_FUNC |
|
435 __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupIgnore, InvalidStatePanic(EBTBURStateBackupIgnore, iStateMachine->GetCurrentState())); |
|
436 |
|
437 // Destroy active backup client |
|
438 delete iActiveBackupClient; |
|
439 iActiveBackupClient = NULL; |
|
440 |
|
441 // Next state transition will be invoked when BUR P&S key changes |
|
442 } |
|
443 |
|
444 void CBTManServerBURMgr::HandleStateRestoreRequestL() |
|
445 { |
|
446 LOG_FUNC |
|
447 __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreRequest, InvalidStatePanic(EBTBURStateRestoreRequest, iStateMachine->GetCurrentState())); |
|
448 |
|
449 // We do want a callback here. Even though the actual restore operation has been handled passively, we |
|
450 // still need notificaton that the passive restore has completed (so we can then deal with the file). |
|
451 iActiveBackupDataClient = CBTActiveBackupDataClient::NewL(*this); |
|
452 iActiveBackupClient = CActiveBackupClient::NewL(iActiveBackupDataClient); |
|
453 |
|
454 // Determine if this restore operation affects us and transition to next state based on this outcome |
|
455 if (DoesBURAffectMeL(*iActiveBackupClient)) |
|
456 { |
|
457 // We're affected, proceed with restore |
|
458 iStateMachine->TransitionState(EBTBUREventRestoreProceed); |
|
459 } |
|
460 else |
|
461 { |
|
462 // We're not effected, don't do any restore handling |
|
463 iStateMachine->TransitionState(EBTBUREventRestoreReject); |
|
464 } |
|
465 } |
|
466 |
|
467 void CBTManServerBURMgr::HandleStateRestoreRequestError() |
|
468 { |
|
469 LOG_FUNC |
|
470 __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreRequest, InvalidStatePanic(EBTBURStateRestoreRequest, iStateMachine->GetCurrentState())); |
|
471 |
|
472 // Transition to normal state |
|
473 iStateMachine->TransitionState(EBTBUREventAbortStateAction); |
|
474 } |
|
475 |
|
476 void CBTManServerBURMgr::HandleStateRestoreOngoingL() |
|
477 { |
|
478 LOG_FUNC |
|
479 __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreOngoing, InvalidStatePanic(EBTBURStateRestoreOngoing, iStateMachine->GetCurrentState())); |
|
480 |
|
481 // Cancel any local address requests |
|
482 if (iLocalAddrFetcher) |
|
483 { |
|
484 iLocalAddrFetcher->Cancel(); |
|
485 } |
|
486 |
|
487 // Provide notification that a BUR operation has started. |
|
488 NotifyBUROperationStarted(); |
|
489 |
|
490 // Signal that we're ready for active restore of prepared file |
|
491 // (note that no data is actively restored, but we still need to invoke this method) |
|
492 iActiveBackupClient->ConfirmReadyForBURL(KErrNone); |
|
493 |
|
494 // Next state transition will be invoked when BUR P&S key changes |
|
495 } |
|
496 |
|
497 void CBTManServerBURMgr::HandleStateRestoreOngoingError() |
|
498 { |
|
499 LOG_FUNC |
|
500 __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreOngoing, InvalidStatePanic(EBTBURStateRestoreOngoing, iStateMachine->GetCurrentState())); |
|
501 |
|
502 // Transition to normal state |
|
503 iStateMachine->TransitionState(EBTBUREventAbortStateAction); |
|
504 } |
|
505 |
|
506 void CBTManServerBURMgr::HandleStateRestoreIgnore() |
|
507 { |
|
508 LOG_FUNC |
|
509 __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreIgnore, InvalidStatePanic(EBTBURStateRestoreIgnore, iStateMachine->GetCurrentState())); |
|
510 |
|
511 // Destroy active backup client |
|
512 delete iActiveBackupClient; |
|
513 delete iActiveBackupDataClient; |
|
514 iActiveBackupClient = NULL; |
|
515 iActiveBackupDataClient = NULL; |
|
516 |
|
517 // Next state transition will be invoked when BUR P&S key changes |
|
518 } |
|
519 |
|
520 void CBTManServerBURMgr::HandleStateProcessRestoreFileL() |
|
521 { |
|
522 LOG_FUNC |
|
523 __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateProcessRestoreFile, InvalidStatePanic(EBTBURStateProcessRestoreFile, iStateMachine->GetCurrentState())); |
|
524 |
|
525 // Start restore file processing |
|
526 iRestoreHandler = CBTRestoreHandler::NewL(*this, iBTManServer); |
|
527 iRestoreHandler->RestoreRemoteDeviceTableL(iLocalAddr); |
|
528 |
|
529 iStateMachine->TransitionState(EBTBUREventProcessRestoreFileComplete); |
|
530 } |
|
531 |
|
532 void CBTManServerBURMgr::HandleStateProcessRestoreFileError(TInt aError) |
|
533 { |
|
534 LOG_FUNC |
|
535 __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateProcessRestoreFile, InvalidStatePanic(EBTBURStateProcessRestoreFile, iStateMachine->GetCurrentState())); |
|
536 |
|
537 // Delete restore handler |
|
538 delete iRestoreHandler; |
|
539 iRestoreHandler = NULL; |
|
540 |
|
541 // If aError is anything other than KErrNoMemory, then delete restore file. |
|
542 // OOM errors may be temporary, and a subsequent restore attempt may succeed. |
|
543 if (aError != KErrNoMemory) |
|
544 { |
|
545 DeleteRestoreFile(); |
|
546 } |
|
547 |
|
548 // Transition to normal state |
|
549 iStateMachine->TransitionState(EBTBUREventAbortStateAction); |
|
550 } |
|
551 |
|
552 void CBTManServerBURMgr::HandleStateRestoreFileProcessingComplete() |
|
553 { |
|
554 LOG_FUNC |
|
555 __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreFileProcessingComplete, InvalidStatePanic(EBTBURStateRestoreFileProcessingComplete, iStateMachine->GetCurrentState())); |
|
556 |
|
557 // Delete restore file (we're now done with it) |
|
558 DeleteRestoreFile(); |
|
559 |
|
560 // Delete restore handler |
|
561 delete iRestoreHandler; |
|
562 iRestoreHandler = NULL; |
|
563 |
|
564 iStateMachine->TransitionState(EBTBUREventRestoreFileTransitionNormal); |
|
565 } |
|
566 |
|
567 /** |
|
568 Sends notification to a registered MBTBURNotify instance that a backup or restore operation has started. |
|
569 @see CBTManServerBURMgr::RequestBURNotification() |
|
570 **/ |
|
571 void CBTManServerBURMgr::NotifyBUROperationStarted() |
|
572 { |
|
573 LOG_FUNC |
|
574 __ASSERT_DEBUG(!iBUROperationStartNotified, PANIC(KBTBackupPanicCat, EBTBURMgrBUROperationStartAlreadyNotified)); |
|
575 |
|
576 if (!iBUROperationStartNotified) |
|
577 { |
|
578 iBUROperationStartNotified = ETrue; |
|
579 |
|
580 if (iBURNotify) |
|
581 { |
|
582 iBURNotify->BUROperationStarted(); |
|
583 } |
|
584 } |
|
585 } |
|
586 |
|
587 /** |
|
588 Sends notification to the MBTBURNotify instance that a backup or restore operation has started. |
|
589 This should correspond to a call to NotifyBUROperationStarted(). |
|
590 @see CBTManServerBURMgr::RequestBURNotification() |
|
591 **/ |
|
592 void CBTManServerBURMgr::NotifyBUROperationStopped() |
|
593 { |
|
594 LOG_FUNC |
|
595 __ASSERT_DEBUG(iBUROperationStartNotified, PANIC(KBTBackupPanicCat, EBTBURMgrBUROperationStartNotNotified)); |
|
596 |
|
597 if (iBUROperationStartNotified) |
|
598 { |
|
599 iBUROperationStartNotified = EFalse; |
|
600 |
|
601 if (iBURNotify) |
|
602 { |
|
603 iBURNotify->BUROperationStopped(); |
|
604 } |
|
605 } |
|
606 } |
|
607 |
|
608 /** |
|
609 Sends notification to the MBTBURNotify instance that a backup or restore operation has started. |
|
610 This will send notification only if NotifyBUROperationStarted() has been called without a corresponding |
|
611 call to NotifyBUROperationStopped(). |
|
612 This is intended for use in error situations only. |
|
613 **/ |
|
614 void CBTManServerBURMgr::NotifyAnyBUROperationStopped() |
|
615 { |
|
616 LOG_FUNC |
|
617 |
|
618 // We deliberately want to fail silently here if no stop notification is expected. |
|
619 if (iBUROperationStartNotified) |
|
620 { |
|
621 iBUROperationStartNotified = EFalse; |
|
622 |
|
623 if (iBURNotify) |
|
624 { |
|
625 iBURNotify->BUROperationStopped(); |
|
626 } |
|
627 } |
|
628 } |
|
629 |
|
630 /** |
|
631 Utility function to delete a named file from the private directory of this process on the system drive. |
|
632 This is a best-efforts attempt which fails silently on error. |
|
633 @param aFileName The name of the file to delete. |
|
634 **/ |
|
635 void CBTManServerBURMgr::DeleteFile(const TDesC& aFileName) |
|
636 { |
|
637 LOG_FUNC |
|
638 |
|
639 RFs fsSession; |
|
640 // Attempt to delete file |
|
641 // This is best-efforts, failing silently on any error (as there is no remedy action that we can take). |
|
642 if (fsSession.Connect() == KErrNone) |
|
643 { |
|
644 if (fsSession.SetSessionToPrivate(fsSession.GetSystemDrive()) == KErrNone) |
|
645 { |
|
646 // Try to ensure read-only and system attributes are not set |
|
647 TUint attrs; |
|
648 TInt err = fsSession.Att(aFileName, attrs); |
|
649 if (err == KErrNone) |
|
650 { |
|
651 // Unset the files read-only and system attributes if these are set. |
|
652 TUint unsetAttrs = (attrs & KEntryAttReadOnly) | (attrs & KEntryAttSystem); |
|
653 if (unsetAttrs != KEntryAttNormal) |
|
654 { |
|
655 err = fsSession.SetAtt(aFileName, KEntryAttNormal, unsetAttrs); |
|
656 } |
|
657 |
|
658 // Attempt to delete the file, if we've managed to successfully retrieve and reset the file attributes. |
|
659 // Note that this is best-efforts. |
|
660 if (err == KErrNone) |
|
661 { |
|
662 static_cast<void>(fsSession.Delete(aFileName)); |
|
663 } |
|
664 } |
|
665 } |
|
666 |
|
667 fsSession.Close(); |
|
668 } |
|
669 } |
|
670 |
|
671 /** |
|
672 Deletes the backup file (with name KBTManServerBackupFileName) from the private directory of this process on the system drive. |
|
673 This is a best-efforts attempt which fails silently on error. |
|
674 **/ |
|
675 void CBTManServerBURMgr::DeleteBackupFile() |
|
676 { |
|
677 LOG_FUNC |
|
678 |
|
679 DeleteFile(KBTManServerBackupFileName); |
|
680 } |
|
681 |
|
682 /** |
|
683 Deletes the restore file (with name KBTManServerRestoreFileName) from the private directory of this process on the system drive. |
|
684 This is a best-efforts attempt which fails silently on error. |
|
685 **/ |
|
686 void CBTManServerBURMgr::DeleteRestoreFile() |
|
687 { |
|
688 LOG_FUNC |
|
689 |
|
690 DeleteFile(KBTManServerRestoreFileName); |
|
691 } |
|
692 |
|
693 /** |
|
694 Renames a restored backup file from KBTManServerBackupFileName to KBTManServerRestoreFileName. |
|
695 This facilitates processing of the restore file when the Bluetooth Manager server next starts. |
|
696 This is a best-efforts attempt, as no remedial action can be taken if this operation fails. |
|
697 **/ |
|
698 void CBTManServerBURMgr::RenameBackupFileForRestore() |
|
699 { |
|
700 LOG_FUNC |
|
701 |
|
702 // Delete any previous restore file |
|
703 DeleteRestoreFile(); |
|
704 |
|
705 RFs fsSession; |
|
706 if (fsSession.Connect() == KErrNone) |
|
707 { |
|
708 static_cast<void>(fsSession.Rename(KBTManServerBackupFileName, KBTManServerRestoreFileName)); |
|
709 fsSession.Close(); |
|
710 } |
|
711 } |
|
712 |
|
713 /** |
|
714 Parses the restore file and updates the loal device name in the registry. |
|
715 This update takes place as soon as the restore file is available, regardless of whether or not the local device |
|
716 address matches that held in the registry. If the local device name has already been set to a non-default value, |
|
717 then it is not modified. |
|
718 **/ |
|
719 void CBTManServerBURMgr::UpdateLocalDeviceNameL() |
|
720 { |
|
721 LOG_FUNC |
|
722 |
|
723 CBTRestoreHandler* restoreHandler = CBTRestoreHandler::NewL(*this, iBTManServer); |
|
724 CleanupStack::PushL(restoreHandler); |
|
725 |
|
726 restoreHandler->RestoreLocalDeviceNameL(); |
|
727 |
|
728 CleanupStack::PopAndDestroy(restoreHandler); |
|
729 } |
|
730 |
|
731 void CBTManServerBURMgr::RunL() |
|
732 { |
|
733 LOG_FUNC |
|
734 |
|
735 if (iStatus == KErrNone) |
|
736 { |
|
737 // Subscribe to catch the next transition |
|
738 SubscribeToBackupRestoreKey(); |
|
739 |
|
740 // Handle this event |
|
741 TInt backupKeyValue = 0; |
|
742 LEAVEIFERRORL(iProperty.Get(backupKeyValue)); |
|
743 TBURPartType backupState = GetBURPartType(backupKeyValue); |
|
744 |
|
745 ProcessBackupState(backupState); |
|
746 } |
|
747 } |
|
748 |
|
749 TInt CBTManServerBURMgr::RunError(TInt /*aError*/) |
|
750 { |
|
751 LOG_FUNC |
|
752 |
|
753 // Problem occured in obtaining backup key value. |
|
754 // Ignore the error, as there is nothing we can do. |
|
755 return KErrNone; |
|
756 } |
|
757 |
|
758 void CBTManServerBURMgr::DoCancel() |
|
759 { |
|
760 LOG_FUNC |
|
761 |
|
762 // Cancel our subscription |
|
763 iProperty.Cancel(); |
|
764 } |
|
765 |
|
766 /** |
|
767 CBTBackupHandler - Handles the task of backing up the BT registry into a backup file ready for passive backup. |
|
768 **/ |
|
769 CBTBackupHandler* CBTBackupHandler::NewL(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry) |
|
770 { |
|
771 LOG_STATIC_FUNC |
|
772 |
|
773 CBTBackupHandler* result = new(ELeave) CBTBackupHandler(aBURMgr, aRegistry); |
|
774 CleanupStack::PushL(result); |
|
775 result->ConstructL(); |
|
776 CleanupStack::Pop(result); |
|
777 return result; |
|
778 } |
|
779 |
|
780 CBTBackupHandler::CBTBackupHandler(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry) |
|
781 : iBURMgr(aBURMgr), |
|
782 iRegistry(aRegistry) |
|
783 { |
|
784 LOG_FUNC |
|
785 } |
|
786 |
|
787 void CBTBackupHandler::ConstructL() |
|
788 { |
|
789 LOG_FUNC |
|
790 |
|
791 iRegistryData=CBTRegistryBURData::NewL(); |
|
792 } |
|
793 |
|
794 CBTBackupHandler::~CBTBackupHandler() |
|
795 { |
|
796 LOG_FUNC |
|
797 |
|
798 delete iRegistryData; |
|
799 } |
|
800 |
|
801 void CBTBackupHandler::CreateBackupFileL() |
|
802 { |
|
803 LOG_FUNC |
|
804 |
|
805 // Collect backup registry data |
|
806 iRegistryData->ReadFromRegistryL(iRegistry); |
|
807 |
|
808 // Only continue if the registry is populated (i.e. it may be in its default state, which does not need to be backed up). |
|
809 // Determine this by examining the local device address stored in the registry. The default registry has this set to 0x0. |
|
810 if (iRegistryData->IsLocalAddressNonZeroL()) |
|
811 { |
|
812 // Construct backup file in private directory. |
|
813 RFs fsSession; |
|
814 LEAVEIFERRORL(fsSession.Connect()); |
|
815 CleanupClosePushL(fsSession); |
|
816 LEAVEIFERRORL(fsSession.SetSessionToPrivate(fsSession.GetSystemDrive())); |
|
817 // Create private path if it does not already exist. |
|
818 LEAVEIFERRORL(fsSession.CreatePrivatePath(fsSession.GetSystemDrive())); |
|
819 |
|
820 RFileWriteStream fStream; |
|
821 // Create backup file, overwriting if necessary (don't care about previous backup files). |
|
822 LEAVEIFERRORL(fStream.Replace(fsSession, KBTManServerBackupFileName, EFileWrite)); |
|
823 fStream.PushL(); |
|
824 |
|
825 // Write out data |
|
826 iRegistryData->WriteToStreamL(fStream); |
|
827 fStream.CommitL(); |
|
828 |
|
829 CleanupStack::PopAndDestroy(2, &fsSession); |
|
830 } |
|
831 } |
|
832 |
|
833 /** |
|
834 CBTRestoreHandler - Handles the task of restoring the BT registry from a restore file given by passive restore. |
|
835 **/ |
|
836 CBTRestoreHandler* CBTRestoreHandler::NewL(CBTManServerBURMgr& aBURMgr, CBTManServer& aManServer) |
|
837 { |
|
838 LOG_STATIC_FUNC |
|
839 |
|
840 CBTRestoreHandler* result = new(ELeave) CBTRestoreHandler(aBURMgr, aManServer); |
|
841 CleanupStack::PushL(result); |
|
842 result->ConstructL(); |
|
843 CleanupStack::Pop(result); |
|
844 return result; |
|
845 } |
|
846 |
|
847 CBTRestoreHandler::CBTRestoreHandler(CBTManServerBURMgr& aBURMgr, CBTManServer& aManServer) |
|
848 : iBURMgr(aBURMgr), |
|
849 iManServer(aManServer) |
|
850 { |
|
851 LOG_FUNC |
|
852 } |
|
853 |
|
854 void CBTRestoreHandler::ConstructL() |
|
855 { |
|
856 LOG_FUNC |
|
857 |
|
858 iRegistryData = CBTRegistryBURData::NewL(); |
|
859 } |
|
860 |
|
861 CBTRestoreHandler::~CBTRestoreHandler() |
|
862 { |
|
863 LOG_FUNC |
|
864 |
|
865 delete iRegistryData; |
|
866 } |
|
867 |
|
868 void CBTRestoreHandler::RestoreLocalDeviceNameL() |
|
869 { |
|
870 LOG_FUNC |
|
871 |
|
872 LoadRestoreDataL(); |
|
873 |
|
874 // If the local device name is still default, restore without validating the local address |
|
875 // (otherwise we will not be able to restore this field before the next stack start, which may cause problems with some UIs) |
|
876 CBTRegistry& registry = iManServer.Registry(); |
|
877 if (iRegistryData->WriteLocalDeviceNameToRegistryL(registry)) |
|
878 { |
|
879 NotifyLocalTableChange(); |
|
880 } |
|
881 } |
|
882 |
|
883 void CBTRestoreHandler::RestoreRemoteDeviceTableL(TBTDevAddr& aLocalAddr) |
|
884 { |
|
885 LOG_FUNC |
|
886 __ASSERT_DEBUG(aLocalAddr != TBTDevAddr(), PANIC(KBTBackupPanicCat, EBTBURMgrMissingLocalAddress)); |
|
887 |
|
888 LoadRestoreDataL(); |
|
889 |
|
890 // Compare local address held in restore file with our local address |
|
891 if (iRegistryData->IsLocalAddressEqualL(aLocalAddr)) |
|
892 { |
|
893 // Proceed with restore of remote devices table |
|
894 CBTRegistry& registry = iManServer.Registry(); |
|
895 |
|
896 TInt noRemoteDevices = iRegistryData->CountRemoteDevicesL(); |
|
897 for (TInt i = 0; i < noRemoteDevices; i++) |
|
898 { |
|
899 if (iRegistryData->WriteRemoteDeviceToRegistryL(registry, i)) |
|
900 { |
|
901 NotifyRemoteTableChangeL(iRegistryData->GetRemoteDeviceL(i).BDAddr()); |
|
902 } |
|
903 } |
|
904 } |
|
905 } |
|
906 |
|
907 void CBTRestoreHandler::LoadRestoreDataL() |
|
908 { |
|
909 LOG_FUNC |
|
910 |
|
911 // Read restore file |
|
912 RFs fsSession; |
|
913 LEAVEIFERRORL(fsSession.Connect()); |
|
914 CleanupClosePushL(fsSession); |
|
915 LEAVEIFERRORL(fsSession.SetSessionToPrivate(fsSession.GetSystemDrive())); |
|
916 // Assuming private directory exists at this point |
|
917 |
|
918 RFileReadStream fStream; |
|
919 LEAVEIFERRORL(fStream.Open(fsSession, KBTManServerRestoreFileName, EFileRead)); |
|
920 fStream.PushL(); |
|
921 |
|
922 // Read in data |
|
923 iRegistryData->ReadFromStreamL(fStream); |
|
924 |
|
925 // Cleanup |
|
926 CleanupStack::PopAndDestroy(2, &fsSession); //fStream and fsSession |
|
927 } |
|
928 |
|
929 /** |
|
930 Sends a notification that the persistence table has been changed. |
|
931 The notification is observable through the P&S key KPropertyKeyBluetoothGetRegistryTableChange. |
|
932 **/ |
|
933 void CBTRestoreHandler::NotifyLocalTableChange() |
|
934 { |
|
935 LOG_FUNC |
|
936 |
|
937 // Notify the P&S key that the remote devices table has changed |
|
938 iManServer.Publish(KPropertyKeyBluetoothGetRegistryTableChange, KRegistryChangeLocalTable); |
|
939 } |
|
940 |
|
941 /** |
|
942 Sends a notification that a device in the remote devices table has been changed. |
|
943 The notification is observable through the P&S key KPropertyKeyBluetoothGetRegistryTableChange. |
|
944 Interested parties can also use RBTRegistry::NotifyViewChange() to detect if the change affects their view. |
|
945 **/ |
|
946 void CBTRestoreHandler::NotifyRemoteTableChangeL(const TBTDevAddr& aAddress) |
|
947 { |
|
948 LOG_FUNC |
|
949 |
|
950 // Construct SQL constraint which selects the device |
|
951 RBTDbQuery query; |
|
952 CleanupClosePushL(query); |
|
953 query.FindDeviceL(aAddress); |
|
954 |
|
955 HBufC* conDes = query.ConstraintBuf().AllocLC(); |
|
956 |
|
957 // Notify the P&S key that the remote devices table has changed |
|
958 iManServer.Publish(KPropertyKeyBluetoothGetRegistryTableChange, KRegistryChangeRemoteTable); |
|
959 |
|
960 // Signal notifiers waiting on view change |
|
961 iManServer.NotifyViewChange(*conDes); |
|
962 |
|
963 // Cleanup constDes and query |
|
964 CleanupStack::PopAndDestroy(2, &query); |
|
965 } |
|
966 |
|
967 /** |
|
968 CBTRegistryBURData - manages data from the Bluetooth registry that is to be backed up or restored. |
|
969 **/ |
|
970 CBTRegistryBURData* CBTRegistryBURData::NewL() |
|
971 { |
|
972 LOG_STATIC_FUNC |
|
973 |
|
974 CBTRegistryBURData* self = new(ELeave) CBTRegistryBURData(); |
|
975 CleanupStack::PushL(self); |
|
976 self->ConstructL(); |
|
977 CleanupStack::Pop(self); |
|
978 return self; |
|
979 } |
|
980 |
|
981 CBTRegistryBURData::CBTRegistryBURData() |
|
982 : iHasRegistryData(EFalse) |
|
983 { |
|
984 LOG_FUNC |
|
985 } |
|
986 |
|
987 CBTRegistryBURData::~CBTRegistryBURData() |
|
988 { |
|
989 LOG_FUNC |
|
990 |
|
991 if (iRemoteDevices) // Dont use ClearRegistryData() here as leave may have occured in ReadFromRegistryL() or ReadFromStreamL() |
|
992 { |
|
993 // Destroy all CBTDevices in iRemoteDevices (necessary before array deletion for CArrayPtrFlat) |
|
994 iRemoteDevices->ResetAndDestroy(); |
|
995 } |
|
996 |
|
997 delete iLocalDevice; |
|
998 delete iRemoteDevicesSid; |
|
999 delete iRemoteDevices; |
|
1000 } |
|
1001 |
|
1002 void CBTRegistryBURData::ConstructL() |
|
1003 { |
|
1004 LOG_FUNC |
|
1005 |
|
1006 iRemoteDevicesSid = new (ELeave) CArrayFixFlat<TSecureId>(1); |
|
1007 iRemoteDevices = new(ELeave) CBTDeviceArray(1); |
|
1008 } |
|
1009 |
|
1010 /** |
|
1011 Writes the registry data held in this instance to a given stream. |
|
1012 This does not write those registry fields which contain unset values. |
|
1013 @param aStream The stream to write the registry data to. |
|
1014 **/ |
|
1015 void CBTRegistryBURData::WriteToStreamL(RWriteStream& aStream) const |
|
1016 { |
|
1017 LOG_FUNC |
|
1018 |
|
1019 // Writes registry data out to a given stream, avoiding any use of class externalisation. |
|
1020 if (HasRegistryData()) |
|
1021 { |
|
1022 // This follows a specific file-format (tied to the registry version information), which is documented seperately. |
|
1023 |
|
1024 // We should already have the following information for the local device. |
|
1025 __ASSERT_DEBUG(iLocalDevice->IsValidAddress(), PANIC(KBTBackupPanicCat, EBTBURMgrExpectedDataMissing)); |
|
1026 |
|
1027 // Write out version information |
|
1028 aStream.WriteUint32L(iRegistryVersionMajor); |
|
1029 aStream.WriteUint32L(iRegistryVersionMinor); |
|
1030 |
|
1031 // Persistence table: |
|
1032 // Local device address and name only (both are mandatory). |
|
1033 aStream.WriteL(iLocalDevice->Address().Des(), KBTDevAddrSize); |
|
1034 |
|
1035 __ASSERT_DEBUG(iLocalDevice->DeviceName().Length() <= KMaxTUint8, PANIC(KBTBackupPanicCat, EBTBURMgrDescriptorLengthTooLong)); |
|
1036 aStream.WriteUint8L(iLocalDevice->DeviceName().Length()); |
|
1037 aStream.WriteL(iLocalDevice->DeviceName(), iLocalDevice->DeviceName().Length()); |
|
1038 |
|
1039 // Remote devices table |
|
1040 TInt rdCount=CountRemoteDevicesL(); |
|
1041 |
|
1042 aStream.WriteUint32L(rdCount); |
|
1043 for (TInt i = 0; i < rdCount; i++) |
|
1044 { |
|
1045 const CBTDevice& nextRemDev = GetRemoteDeviceL(i); |
|
1046 const TBTNamelessDevice& nextRemDevNameless = nextRemDev.AsNamelessDevice(); |
|
1047 |
|
1048 __ASSERT_DEBUG(nextRemDev.IsValidBDAddr(), PANIC(KBTBackupPanicCat, EBTBURMgrExpectedDataMissing)); |
|
1049 |
|
1050 // Work out what is set and derive bitmask (can use TBTDeviceSet here as is public) |
|
1051 TUint32 rdSetMask = TBTNamelessDevice::EAddress; |
|
1052 if (nextRemDev.IsValidDeviceClass()) |
|
1053 { |
|
1054 rdSetMask |= TBTNamelessDevice::EDeviceClass; |
|
1055 } |
|
1056 if (nextRemDev.IsValidLinkKey()) |
|
1057 { |
|
1058 rdSetMask |= TBTNamelessDevice::ELinkKey; |
|
1059 } |
|
1060 if (nextRemDev.IsValidGlobalSecurity()) |
|
1061 { |
|
1062 rdSetMask |= TBTNamelessDevice::EGlobalSecurity; |
|
1063 } |
|
1064 if (nextRemDevNameless.IsValidPageScanRepMode()) |
|
1065 { |
|
1066 rdSetMask |= TBTNamelessDevice::EPageScanRepMode; |
|
1067 } |
|
1068 if (nextRemDevNameless.IsValidPageScanMode()) |
|
1069 { |
|
1070 rdSetMask |= TBTNamelessDevice::EPageScanMode; |
|
1071 } |
|
1072 if (nextRemDevNameless.IsValidPageScanPeriodMode()) |
|
1073 { |
|
1074 rdSetMask |= TBTNamelessDevice::EPageScanPeriodMode; |
|
1075 } |
|
1076 if (nextRemDevNameless.IsValidClockOffset()) |
|
1077 { |
|
1078 rdSetMask |= TBTNamelessDevice::EClockOffset; |
|
1079 } |
|
1080 if (nextRemDev.IsValidUsed()) |
|
1081 { |
|
1082 rdSetMask |= TBTNamelessDevice::EUsed; |
|
1083 } |
|
1084 if (nextRemDev.IsValidSeen()) |
|
1085 { |
|
1086 rdSetMask |= TBTNamelessDevice::ESeen; |
|
1087 } |
|
1088 if (nextRemDev.IsValidPassKey()) |
|
1089 { |
|
1090 rdSetMask |= TBTNamelessDevice::EPassKey; |
|
1091 } |
|
1092 if (nextRemDev.IsValidUiCookie()) |
|
1093 { |
|
1094 rdSetMask |= TBTNamelessDevice::EUiCookie; |
|
1095 } |
|
1096 if (nextRemDev.IsValidDeviceName()) |
|
1097 { |
|
1098 rdSetMask |= CBTDevice::EDeviceName; |
|
1099 } |
|
1100 if (nextRemDev.IsValidFriendlyName()) |
|
1101 { |
|
1102 rdSetMask |= CBTDevice::EFriendlyName; |
|
1103 } |
|
1104 // Now write out bitmask |
|
1105 aStream.WriteUint32L(rdSetMask); |
|
1106 |
|
1107 // Write valid setting for next remote device |
|
1108 aStream.WriteUint32L(GetRemoteDeviceEntrySidL(i)); |
|
1109 aStream.WriteL(nextRemDev.BDAddr().Des(), KBTDevAddrSize); |
|
1110 if (rdSetMask & TBTNamelessDevice::EDeviceClass) |
|
1111 { |
|
1112 aStream.WriteUint32L(nextRemDev.DeviceClass().DeviceClass()); |
|
1113 } |
|
1114 if (rdSetMask & TBTNamelessDevice::ELinkKey) |
|
1115 { |
|
1116 const TBTLinkKey& nextRemDevLinkKey = nextRemDev.LinkKey(); |
|
1117 aStream.WriteL(nextRemDevLinkKey, KHCILinkKeySize); |
|
1118 aStream.WriteUint8L(nextRemDev.LinkKeyType()); |
|
1119 } |
|
1120 if (rdSetMask & TBTNamelessDevice::EGlobalSecurity) |
|
1121 { |
|
1122 TBTDeviceSecurity nextRemDevGlobSec = nextRemDev.GlobalSecurity(); |
|
1123 aStream.WriteUint8L(nextRemDevGlobSec.SecurityValue()); |
|
1124 aStream.WriteUint32L(nextRemDevGlobSec.PasskeyMinLength()); |
|
1125 } |
|
1126 if (rdSetMask & TBTNamelessDevice::EPageScanRepMode) |
|
1127 { |
|
1128 aStream.WriteUint8L(nextRemDevNameless.PageScanRepMode()); |
|
1129 } |
|
1130 if (rdSetMask & TBTNamelessDevice::EPageScanMode) |
|
1131 { |
|
1132 aStream.WriteUint8L(nextRemDevNameless.PageScanMode()); |
|
1133 } |
|
1134 if (rdSetMask & TBTNamelessDevice::EPageScanPeriodMode) |
|
1135 { |
|
1136 aStream.WriteUint8L(nextRemDevNameless.PageScanPeriodMode()); |
|
1137 } |
|
1138 if (rdSetMask & TBTNamelessDevice::EClockOffset) |
|
1139 { |
|
1140 aStream.WriteUint16L(nextRemDevNameless.ClockOffset()); |
|
1141 } |
|
1142 if (rdSetMask & TBTNamelessDevice::EUsed) |
|
1143 { |
|
1144 const TInt64& used = nextRemDev.Used().Int64(); |
|
1145 aStream.WriteInt32L(I64HIGH(used)); |
|
1146 aStream.WriteInt32L(I64LOW(used)); |
|
1147 } |
|
1148 if (rdSetMask & TBTNamelessDevice::ESeen) |
|
1149 { |
|
1150 const TInt64& seen = nextRemDev.Seen().Int64(); |
|
1151 aStream.WriteInt32L(I64HIGH(seen)); |
|
1152 aStream.WriteInt32L(I64LOW(seen)); |
|
1153 } |
|
1154 if (rdSetMask & TBTNamelessDevice::EPassKey) |
|
1155 { |
|
1156 const TBTPinCode& nextRemDevPassKey = nextRemDev.PassKey(); |
|
1157 __ASSERT_DEBUG(nextRemDevPassKey.Length() == KHCIPINCodeSize + 1, PANIC(KBTBackupPanicCat, EBTBURMgrDescriptorUnexpectedLength)); |
|
1158 aStream.WriteL(nextRemDevPassKey, KHCIPINCodeSize + 1); |
|
1159 } |
|
1160 if (rdSetMask & TBTNamelessDevice::EUiCookie) |
|
1161 { |
|
1162 aStream.WriteUint32L(nextRemDev.UiCookie()); |
|
1163 } |
|
1164 if (rdSetMask & CBTDevice::EDeviceName) |
|
1165 { |
|
1166 __ASSERT_DEBUG(nextRemDev.DeviceName().Length() <= KMaxTUint8, PANIC(KBTBackupPanicCat, EBTBURMgrDescriptorLengthTooLong)); |
|
1167 aStream.WriteUint8L(nextRemDev.DeviceName().Length()); |
|
1168 aStream.WriteL(nextRemDev.DeviceName(), nextRemDev.DeviceName().Length()); |
|
1169 } |
|
1170 if (rdSetMask & CBTDevice::EFriendlyName) |
|
1171 { |
|
1172 __ASSERT_DEBUG(nextRemDev.FriendlyName().Length() <= KMaxTUint8, PANIC(KBTBackupPanicCat, EBTBURMgrDescriptorLengthTooLong)); |
|
1173 aStream.WriteUint8L(nextRemDev.FriendlyName().Length()); |
|
1174 aStream.WriteL(nextRemDev.FriendlyName(), nextRemDev.FriendlyName().Length()); |
|
1175 } |
|
1176 } |
|
1177 } |
|
1178 else |
|
1179 { |
|
1180 User::Leave(KErrNotFound); |
|
1181 } |
|
1182 } |
|
1183 |
|
1184 /** |
|
1185 Reads registry data from a given stream and stores within this instance. |
|
1186 Any registry data currently held is cleared first. |
|
1187 @param aStream The stream to ready the registry data from. |
|
1188 **/ |
|
1189 void CBTRegistryBURData::ReadFromStreamL(RReadStream& aStream) |
|
1190 { |
|
1191 LOG_FUNC |
|
1192 |
|
1193 // This follows a specific file-format (tied to the registry version information), which is documented seperately. |
|
1194 |
|
1195 // Note that we dont make *ANY* assumptions as to what data should always be available, since the restore file could be corrupt. |
|
1196 // We will fail the restore if it turns out we do not have enough information, or if we have invalid information. |
|
1197 |
|
1198 // WARNING: When a new registry version is produced, this implementaton of backup/restore support will need modification. |
|
1199 // This assert should be updated to include all supported registry versions. |
|
1200 __ASSERT_DEBUG(KRegistryDBVersionMajor == 1 && KRegistryDBVersionMinor == 2, PANIC(KBTBackupPanicCat, EBTBURMgrUnsupportedRegistryVersion)); |
|
1201 |
|
1202 // Extract version information and continue if we can handle it. |
|
1203 TUint32 regVersionMajor = aStream.ReadUint32L(); |
|
1204 TUint32 regVersionMinor = aStream.ReadUint32L(); |
|
1205 if (regVersionMajor == KRegistryDBVersionMajor && regVersionMinor == KRegistryDBVersionMinor) |
|
1206 { |
|
1207 // We support this version and this version only - read in registry data |
|
1208 ClearRegistryData(); |
|
1209 |
|
1210 iLocalDevice = new(ELeave) TBTLocalDevice; |
|
1211 |
|
1212 // Note version information for this registry |
|
1213 iRegistryVersionMajor = regVersionMajor; |
|
1214 iRegistryVersionMinor = regVersionMinor; |
|
1215 |
|
1216 // Persistence table: |
|
1217 // Local device address and name only (both fields are mandatory). |
|
1218 TBTDevAddr address; |
|
1219 TPtr8 addrPtr(address.Des()); |
|
1220 aStream.ReadL(addrPtr, KBTDevAddrSize); |
|
1221 if (addrPtr.Length() == KBTDevAddrSize) |
|
1222 { |
|
1223 iLocalDevice->SetAddress(address); |
|
1224 } |
|
1225 else |
|
1226 { |
|
1227 User::Leave(KErrCorrupt); |
|
1228 } |
|
1229 |
|
1230 TInt deviceNameLength = static_cast<TInt>(aStream.ReadUint8L()); |
|
1231 if (deviceNameLength <= KMaxBluetoothNameLen) |
|
1232 { |
|
1233 RBuf8 deviceName; |
|
1234 deviceName.CreateL(KMaxBluetoothNameLen); |
|
1235 CleanupClosePushL(deviceName); |
|
1236 |
|
1237 aStream.ReadL(deviceName,deviceNameLength); |
|
1238 if (deviceName.Length() == deviceNameLength) |
|
1239 { |
|
1240 iLocalDevice->SetDeviceName(deviceName); |
|
1241 } |
|
1242 else |
|
1243 { |
|
1244 User::Leave(KErrCorrupt); |
|
1245 } |
|
1246 CleanupStack::PopAndDestroy(&deviceName); |
|
1247 } |
|
1248 else |
|
1249 { |
|
1250 User::Leave(KErrCorrupt); |
|
1251 } |
|
1252 |
|
1253 // Remote devices table: |
|
1254 TInt rdCount = aStream.ReadUint32L(); |
|
1255 for (TInt i = 0; i < rdCount; i++) |
|
1256 { |
|
1257 // First read bitmask of available data |
|
1258 TUint32 rdSetMask = aStream.ReadUint32L(); |
|
1259 |
|
1260 // Then read available data from file and store |
|
1261 CBTDevice *rdInstance = CBTDevice::NewLC(); |
|
1262 TBTNamelessDevice& rdNamelessDevInstance = rdInstance->AsNamelessDevice(); |
|
1263 TSecureId rdSid = aStream.ReadUint32L(); |
|
1264 |
|
1265 // Remote BT address is mandatory |
|
1266 if (rdSetMask & TBTNamelessDevice::EAddress) |
|
1267 { |
|
1268 TBTDevAddr rdAddr; |
|
1269 TPtr8 rdAddrPtr(rdAddr.Des()); |
|
1270 aStream.ReadL(rdAddrPtr, KBTDevAddrSize); |
|
1271 |
|
1272 // Ensure address is of required length and is non-zero |
|
1273 if (rdAddrPtr.Length() == KBTDevAddrSize && rdAddr != TBTDevAddr()) |
|
1274 { |
|
1275 rdInstance->SetDeviceAddress(rdAddr); |
|
1276 } |
|
1277 else |
|
1278 { |
|
1279 User::Leave(KErrCorrupt); |
|
1280 } |
|
1281 } |
|
1282 else |
|
1283 { |
|
1284 User::Leave(KErrCorrupt); |
|
1285 } |
|
1286 |
|
1287 if (rdSetMask & TBTNamelessDevice::EDeviceClass) |
|
1288 { |
|
1289 TBTDeviceClass rdClass = TBTDeviceClass(aStream.ReadUint32L()); |
|
1290 rdInstance->SetDeviceClass(rdClass); |
|
1291 } |
|
1292 |
|
1293 if (rdSetMask & TBTNamelessDevice::ELinkKey) |
|
1294 { |
|
1295 TBTLinkKey rdLinkKey; |
|
1296 aStream.ReadL(rdLinkKey, KHCILinkKeySize); |
|
1297 if (rdLinkKey.Length() == KHCILinkKeySize) |
|
1298 { |
|
1299 TUint8 rdLinkKeyType = static_cast<TBTLinkKeyType>(aStream.ReadUint8L()); |
|
1300 // Ensure value is in the valid range (ELinkKeyCombination is zero so (pointless) comparison with this gives warnings). |
|
1301 if (rdLinkKeyType <= ELinkKeyDebug) |
|
1302 { |
|
1303 rdInstance->SetLinkKey(rdLinkKey, static_cast<TBTLinkKeyType>(rdLinkKeyType)); |
|
1304 } |
|
1305 else |
|
1306 { |
|
1307 User::Leave(KErrCorrupt); |
|
1308 } |
|
1309 |
|
1310 } |
|
1311 else |
|
1312 { |
|
1313 User::Leave(KErrCorrupt); |
|
1314 } |
|
1315 } |
|
1316 |
|
1317 if (rdSetMask & TBTNamelessDevice::EGlobalSecurity) |
|
1318 { |
|
1319 TBTDeviceSecurity rdGlobSec; |
|
1320 TUint8 globSecValue = aStream.ReadUint8L(); |
|
1321 // Ensure value is in the valid range (lower value is zero so (pointless) comparison with this gives warnings). |
|
1322 if (globSecValue <= KBTBURMgrMaxGlobalSecurityValue) |
|
1323 { |
|
1324 rdGlobSec.SetSecurityValue(globSecValue); |
|
1325 |
|
1326 TUint32 passKeyMinLen = aStream.ReadUint32L(); |
|
1327 |
|
1328 if (passKeyMinLen <= KHCIPINCodeSize) |
|
1329 { |
|
1330 rdGlobSec.SetPasskeyMinLength(passKeyMinLen); |
|
1331 rdInstance->SetGlobalSecurity(rdGlobSec); |
|
1332 } |
|
1333 else |
|
1334 { |
|
1335 User::Leave(KErrCorrupt); |
|
1336 } |
|
1337 } |
|
1338 else |
|
1339 { |
|
1340 User::Leave(KErrCorrupt); |
|
1341 } |
|
1342 } |
|
1343 |
|
1344 if (rdSetMask & TBTNamelessDevice::EPageScanRepMode) |
|
1345 { |
|
1346 TUint8 rdPageScanRepMode = aStream.ReadUint8L(); |
|
1347 // Ensure value is in the valid range (lower value is zero so (pointless) comparison with this gives warnings). |
|
1348 if (rdPageScanRepMode <= EPageScanModeR2) |
|
1349 { |
|
1350 rdNamelessDevInstance.SetPageScanRepMode(rdPageScanRepMode); |
|
1351 } |
|
1352 else |
|
1353 { |
|
1354 User::Leave(KErrCorrupt); |
|
1355 } |
|
1356 } |
|
1357 |
|
1358 if (rdSetMask & TBTNamelessDevice::EPageScanMode) |
|
1359 { |
|
1360 TUint8 rdPageScanMode = aStream.ReadUint8L(); |
|
1361 // Ensure value is in the valid range (lower value is zero so (pointless) comparison with this gives warnings). |
|
1362 if (rdPageScanMode <= KBTBURMgrMaxPageScanMode) |
|
1363 { |
|
1364 rdNamelessDevInstance.SetPageScanMode(rdPageScanMode); |
|
1365 } |
|
1366 else |
|
1367 { |
|
1368 User::Leave(KErrCorrupt); |
|
1369 } |
|
1370 } |
|
1371 |
|
1372 if (rdSetMask & TBTNamelessDevice::EPageScanPeriodMode) |
|
1373 { |
|
1374 TUint8 rdPageScanPeriodMode = aStream.ReadUint8L(); |
|
1375 // Ensure value is in the valid range (lower value is zero so (pointless) comparison with this gives warnings). |
|
1376 if (rdPageScanPeriodMode <= KBTBURMgrMaxPageScanPeriodMode) |
|
1377 { |
|
1378 rdNamelessDevInstance.SetPageScanPeriodMode(rdPageScanPeriodMode); |
|
1379 } |
|
1380 else |
|
1381 { |
|
1382 User::Leave(KErrCorrupt); |
|
1383 } |
|
1384 } |
|
1385 |
|
1386 if (rdSetMask & TBTNamelessDevice::EClockOffset) |
|
1387 { |
|
1388 TUint16 rdClockOffset = aStream.ReadUint16L(); |
|
1389 rdNamelessDevInstance.SetClockOffset(rdClockOffset); |
|
1390 } |
|
1391 |
|
1392 if (rdSetMask & TBTNamelessDevice::EUsed) |
|
1393 { |
|
1394 TInt32 usedU = aStream.ReadInt32L(); |
|
1395 TInt32 usedL = aStream.ReadInt32L(); |
|
1396 TInt64 rdUsed = MAKE_TINT64(usedU, usedL); |
|
1397 rdNamelessDevInstance.SetUsed(rdUsed); |
|
1398 } |
|
1399 |
|
1400 if (rdSetMask & TBTNamelessDevice::ESeen) |
|
1401 { |
|
1402 TInt32 seenU = aStream.ReadInt32L(); |
|
1403 TInt32 seenL = aStream.ReadInt32L(); |
|
1404 TInt64 rdSeen = MAKE_TINT64(seenU, seenL); |
|
1405 rdNamelessDevInstance.SetSeen(rdSeen); |
|
1406 } |
|
1407 |
|
1408 if (rdSetMask & TBTNamelessDevice::EPassKey) |
|
1409 { |
|
1410 TBTPinCode rdPassKey; |
|
1411 aStream.ReadL(rdPassKey, KHCIPINCodeSize + 1); |
|
1412 if (rdPassKey.Length() == KHCIPINCodeSize + 1) |
|
1413 { |
|
1414 rdInstance->SetPassKey(rdPassKey); |
|
1415 } |
|
1416 else |
|
1417 { |
|
1418 User::Leave(KErrCorrupt); |
|
1419 } |
|
1420 } |
|
1421 |
|
1422 if (rdSetMask & TBTNamelessDevice::EUiCookie) |
|
1423 { |
|
1424 TUint32 rdUiCookie = aStream.ReadUint32L(); |
|
1425 rdNamelessDevInstance.SetUiCookie(rdUiCookie); |
|
1426 } |
|
1427 |
|
1428 if (rdSetMask & CBTDevice::EDeviceName) |
|
1429 { |
|
1430 TInt rdNameLen = static_cast<TInt>(aStream.ReadUint8L()); |
|
1431 if (rdNameLen <= KMaxBluetoothNameLen) |
|
1432 { |
|
1433 RBuf8 rdName; |
|
1434 rdName.CreateL(KMaxBluetoothNameLen); |
|
1435 CleanupClosePushL(rdName); |
|
1436 |
|
1437 aStream.ReadL(rdName, rdNameLen); |
|
1438 if (rdName.Length() == rdNameLen) |
|
1439 { |
|
1440 rdInstance->SetDeviceNameL(rdName); |
|
1441 } |
|
1442 else |
|
1443 { |
|
1444 User::Leave(KErrCorrupt); |
|
1445 } |
|
1446 CleanupStack::PopAndDestroy(&rdName); |
|
1447 } |
|
1448 else |
|
1449 { |
|
1450 User::Leave(KErrCorrupt); |
|
1451 } |
|
1452 } |
|
1453 |
|
1454 if (rdSetMask & CBTDevice::EFriendlyName) |
|
1455 { |
|
1456 TInt rdFriendlyNameLen = static_cast<TInt>(aStream.ReadUint8L()); |
|
1457 if (rdFriendlyNameLen <= KMaxFriendlyNameLen) |
|
1458 { |
|
1459 RBuf rdFriendlyName; |
|
1460 rdFriendlyName.CreateL(KMaxFriendlyNameLen); |
|
1461 CleanupClosePushL(rdFriendlyName); |
|
1462 |
|
1463 aStream.ReadL(rdFriendlyName, rdFriendlyNameLen); |
|
1464 if (rdFriendlyName.Length() == rdFriendlyNameLen) |
|
1465 { |
|
1466 rdInstance->SetFriendlyNameL(rdFriendlyName); |
|
1467 } |
|
1468 else |
|
1469 { |
|
1470 User::Leave(KErrCorrupt); |
|
1471 } |
|
1472 CleanupStack::PopAndDestroy(&rdFriendlyName); |
|
1473 } |
|
1474 else |
|
1475 { |
|
1476 User::Leave(KErrCorrupt); |
|
1477 } |
|
1478 } |
|
1479 |
|
1480 // Data now stored, add rdInstance to our remote devices list |
|
1481 iRemoteDevices->AppendL(rdInstance); |
|
1482 iRemoteDevicesSid->AppendL(rdSid); |
|
1483 CleanupStack::Pop(rdInstance); |
|
1484 } |
|
1485 |
|
1486 // Mark that we now have registry data |
|
1487 iHasRegistryData = ETrue; |
|
1488 } |
|
1489 } |
|
1490 |
|
1491 /** |
|
1492 Reads registry data from the registry into this instance. |
|
1493 Any existing registry data held in this instance is cleared first. |
|
1494 @param aRegistry The CBTRegistry instance to use for registry access. |
|
1495 **/ |
|
1496 void CBTRegistryBURData::ReadFromRegistryL(CBTRegistry& aRegistry) |
|
1497 { |
|
1498 LOG_FUNC |
|
1499 |
|
1500 ClearRegistryData(); |
|
1501 |
|
1502 // The meta information from our registry is known. |
|
1503 iRegistryVersionMajor = KRegistryDBVersionMajor; |
|
1504 iRegistryVersionMinor = KRegistryDBVersionMinor; |
|
1505 |
|
1506 // Persistence table |
|
1507 iLocalDevice = aRegistry.GetLocalDeviceL(); |
|
1508 |
|
1509 // Remote device table |
|
1510 // Create a view on the table. |
|
1511 RBTDbQuery query; |
|
1512 CleanupClosePushL(query); |
|
1513 TBTRegistrySearch searchCriteria; |
|
1514 searchCriteria.FindAll(); |
|
1515 query.SearchL(searchCriteria); |
|
1516 TDbBookmark bookmark; |
|
1517 RDbView* view = aRegistry.OpenViewL(query, bookmark); |
|
1518 CleanupCloseDeletePushL(view); |
|
1519 |
|
1520 // Populate iRemoteDevices from the view. |
|
1521 while (!view->AtEnd()) |
|
1522 { |
|
1523 CBTDevice *next = aRegistry.GetNextDeviceL(*view, bookmark, ETrue); |
|
1524 CleanupStack::PushL(next); |
|
1525 |
|
1526 // CBTRegisty::CreatingProcessUidL() requires a rowset with exactly one row. |
|
1527 // So we have to requery for this device to get a singular row. |
|
1528 TDbBookmark singleBookmark; |
|
1529 RDbView* singleView = aRegistry.OpenDeviceL(next->BDAddr(), singleBookmark); |
|
1530 CleanupCloseDeletePushL(singleView); |
|
1531 TSecureId nextSid = aRegistry.CreatingProcessUidL(*singleView); |
|
1532 CleanupStack::PopAndDestroy(singleView); |
|
1533 |
|
1534 iRemoteDevices->AppendL(next); |
|
1535 iRemoteDevicesSid->AppendL(nextSid); |
|
1536 |
|
1537 CleanupStack::Pop(next); // iRemoteDevices now takes ownership |
|
1538 } |
|
1539 |
|
1540 CleanupStack::PopAndDestroy(2, &query); // view and query |
|
1541 |
|
1542 // Mark that we now have registry data |
|
1543 iHasRegistryData = ETrue; |
|
1544 } |
|
1545 |
|
1546 /** |
|
1547 Updates the persistence table of the registry with local device name held in this instance |
|
1548 if the registry currently holds a default name. |
|
1549 @param aRegistry The CBTRegistry instance to use for registry access. |
|
1550 @return ETrue if an update was made to the registry. |
|
1551 **/ |
|
1552 TBool CBTRegistryBURData::WriteLocalDeviceNameToRegistryL(CBTRegistry& aRegistry) const |
|
1553 { |
|
1554 LOG_FUNC |
|
1555 |
|
1556 TBool updateDone = EFalse; |
|
1557 |
|
1558 // Update device name only if the registry has a default name |
|
1559 TBTLocalDevice defaultDevice; |
|
1560 TRAP_IGNORE(aRegistry.GetDefaultDeviceFromIniL(defaultDevice)); |
|
1561 |
|
1562 if (!defaultDevice.IsValidDeviceName()) |
|
1563 { |
|
1564 // Could not obtain a default name - use KDefaultLocalName instead |
|
1565 defaultDevice.SetDeviceName(KDefaultLocalName); |
|
1566 } |
|
1567 |
|
1568 TBTLocalDevice* localDevice = aRegistry.GetLocalDeviceL(); |
|
1569 CleanupStack::PushL(localDevice); |
|
1570 |
|
1571 if (localDevice->DeviceName() == defaultDevice.DeviceName()) |
|
1572 { |
|
1573 // Local device name is default, update with restored value. |
|
1574 localDevice->SetDeviceName(GetLocalDeviceNameL()); |
|
1575 aRegistry.UpdateLocalDeviceL(*localDevice); |
|
1576 updateDone = ETrue; |
|
1577 } |
|
1578 |
|
1579 CleanupStack::PopAndDestroy(localDevice); |
|
1580 |
|
1581 return updateDone; |
|
1582 } |
|
1583 |
|
1584 /** |
|
1585 Updates an entry of the remote devices table of the registry with data held in this instance. |
|
1586 If the remote device already exists in the registry, the registry version is updated only if it |
|
1587 does not hold a link key. |
|
1588 Otherwise, the remote device is added to the registry. |
|
1589 @param aRegistry The CBTRegistry instance to use for registry access. |
|
1590 @param aDeviceIndex The remote device held in this CBTRegistryBURData instance to be written to the registry. |
|
1591 @return ETrue if an update was made to the registry. |
|
1592 **/ |
|
1593 TBool CBTRegistryBURData::WriteRemoteDeviceToRegistryL(CBTRegistry& aRegistry, TInt aDeviceIndex) const |
|
1594 { |
|
1595 LOG_FUNC |
|
1596 |
|
1597 TBool updateDone = EFalse; |
|
1598 |
|
1599 // Get device and SID |
|
1600 const CBTDevice& nextRemDevice = GetRemoteDeviceL(aDeviceIndex); |
|
1601 TSecureId nextRemDeviceSid = GetRemoteDeviceEntrySidL(aDeviceIndex); |
|
1602 |
|
1603 // Try to add device to registry. If this fails with KErrAlreadExists, then update existing device. |
|
1604 TRAPD(err, aRegistry.CreateDeviceL(nextRemDevice, nextRemDevice.IsValidUiCookie(), nextRemDeviceSid)); |
|
1605 |
|
1606 if (err == KErrNone) |
|
1607 { |
|
1608 // New device added successfully |
|
1609 updateDone = ETrue; |
|
1610 } |
|
1611 else if (err == KErrAlreadyExists) |
|
1612 { |
|
1613 // Device already exists. Extract and examine |
|
1614 TDbBookmark bookmark; |
|
1615 RDbView* view = aRegistry.OpenDeviceL(nextRemDevice.BDAddr(), bookmark); |
|
1616 CleanupCloseDeletePushL(view); |
|
1617 CBTDevice *regDev = aRegistry.GetNextDeviceL(*view, bookmark, ETrue); |
|
1618 CleanupStack::PushL(regDev); |
|
1619 |
|
1620 if (!regDev->IsValidLinkKey()) |
|
1621 { |
|
1622 // No link key - safe to restore remote device from file. |
|
1623 view->FirstL(); |
|
1624 aRegistry.UpdateDeviceL(*view, nextRemDevice); |
|
1625 updateDone = ETrue; |
|
1626 } |
|
1627 |
|
1628 CleanupStack::PopAndDestroy(2, view); |
|
1629 } |
|
1630 else |
|
1631 { |
|
1632 // Unexpected error - pass upward for handling |
|
1633 User::Leave(err); |
|
1634 } |
|
1635 |
|
1636 return updateDone; |
|
1637 } |
|
1638 |
|
1639 void CBTRegistryBURData::GetRegistryVersionL(TUint32& aRegistryVersionMajor, TUint32& aRegistryVersionMinor) const |
|
1640 { |
|
1641 LOG_FUNC |
|
1642 |
|
1643 if (!HasRegistryData()) |
|
1644 { |
|
1645 User::Leave(KErrNotFound); |
|
1646 } |
|
1647 |
|
1648 aRegistryVersionMajor = iRegistryVersionMajor; |
|
1649 aRegistryVersionMinor = iRegistryVersionMinor; |
|
1650 } |
|
1651 |
|
1652 const TDesC8& CBTRegistryBURData::GetLocalDeviceNameL() const |
|
1653 { |
|
1654 LOG_FUNC |
|
1655 |
|
1656 if (!HasRegistryData()) |
|
1657 { |
|
1658 User::Leave(KErrNotFound); |
|
1659 } |
|
1660 |
|
1661 __ASSERT_DEBUG(iLocalDevice, PANIC(KBTBackupPanicCat, EBTBURMgrExpectedDataMissing)); |
|
1662 return iLocalDevice->DeviceName(); |
|
1663 } |
|
1664 |
|
1665 TBool CBTRegistryBURData::IsLocalAddressNonZeroL() const |
|
1666 { |
|
1667 LOG_FUNC |
|
1668 |
|
1669 TBTDevAddr zeroAddr; |
|
1670 return !IsLocalAddressEqualL(zeroAddr); |
|
1671 } |
|
1672 |
|
1673 TBool CBTRegistryBURData::IsLocalAddressEqualL(TBTDevAddr& aAddr) const |
|
1674 { |
|
1675 LOG_FUNC |
|
1676 |
|
1677 if (!HasRegistryData()) |
|
1678 { |
|
1679 User::Leave(KErrNotFound); |
|
1680 } |
|
1681 |
|
1682 __ASSERT_DEBUG(iLocalDevice, PANIC(KBTBackupPanicCat, EBTBURMgrExpectedDataMissing)); |
|
1683 return (iLocalDevice->Address() == aAddr); |
|
1684 } |
|
1685 |
|
1686 TInt CBTRegistryBURData::CountRemoteDevicesL() const |
|
1687 { |
|
1688 LOG_FUNC |
|
1689 |
|
1690 if (!HasRegistryData()) |
|
1691 { |
|
1692 User::Leave(KErrNotFound); |
|
1693 } |
|
1694 |
|
1695 __ASSERT_DEBUG(iRemoteDevices->Count() == iRemoteDevicesSid->Count(), PANIC(KBTBackupPanicCat, EBTBURMgrArraySizeMisMatch)); |
|
1696 return iRemoteDevices->Count(); |
|
1697 } |
|
1698 |
|
1699 const CBTDevice& CBTRegistryBURData::GetRemoteDeviceL(TInt aDeviceIndex) const |
|
1700 { |
|
1701 LOG_FUNC |
|
1702 |
|
1703 if (!HasRegistryData() || !((aDeviceIndex >= 0) && (aDeviceIndex < iRemoteDevices->Count()))) |
|
1704 { |
|
1705 User::Leave(KErrNotFound); |
|
1706 } |
|
1707 |
|
1708 __ASSERT_DEBUG(iRemoteDevices->Count() == iRemoteDevicesSid->Count(), PANIC(KBTBackupPanicCat, EBTBURMgrArraySizeMisMatch)); |
|
1709 return *(iRemoteDevices->At(aDeviceIndex)); |
|
1710 } |
|
1711 |
|
1712 TSecureId CBTRegistryBURData::GetRemoteDeviceEntrySidL(TInt aDeviceIndex) const |
|
1713 { |
|
1714 LOG_FUNC |
|
1715 |
|
1716 if (!HasRegistryData() || !((aDeviceIndex >= 0) && (aDeviceIndex < iRemoteDevicesSid->Count()))) |
|
1717 { |
|
1718 User::Leave(KErrNotFound); |
|
1719 } |
|
1720 |
|
1721 __ASSERT_DEBUG(iRemoteDevices->Count() == iRemoteDevicesSid->Count(), PANIC(KBTBackupPanicCat, EBTBURMgrArraySizeMisMatch)); |
|
1722 return iRemoteDevicesSid->At(aDeviceIndex); |
|
1723 } |
|
1724 |
|
1725 /** |
|
1726 Clears any registry data stored internally within this instance. |
|
1727 If no data is stored, this method does nothing. |
|
1728 **/ |
|
1729 void CBTRegistryBURData::ClearRegistryData() |
|
1730 { |
|
1731 LOG_FUNC |
|
1732 |
|
1733 // This is a no-op if we have no registry data to clear |
|
1734 if (HasRegistryData()) |
|
1735 { |
|
1736 // Clear data held previously |
|
1737 iRemoteDevicesSid->Reset(); |
|
1738 iRemoteDevices->ResetAndDestroy(); |
|
1739 delete iLocalDevice; |
|
1740 iLocalDevice = NULL; |
|
1741 |
|
1742 iHasRegistryData = EFalse; |
|
1743 } |
|
1744 } |
|
1745 |
|
1746 /** |
|
1747 CBTLocalAddressFetcher - Fetches the local device address, or waits for the addresss to become available, and |
|
1748 passes to CBTManServerBURMgr. |
|
1749 **/ |
|
1750 CBTLocalAddressFetcher* CBTLocalAddressFetcher::NewL(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry, TInt aPriority) |
|
1751 { |
|
1752 LOG_STATIC_FUNC |
|
1753 |
|
1754 CBTLocalAddressFetcher* result = new(ELeave) CBTLocalAddressFetcher(aBURMgr, aRegistry, aPriority); |
|
1755 CleanupStack::PushL(result); |
|
1756 result->ConstructL(); |
|
1757 CleanupStack::Pop(result); |
|
1758 return result; |
|
1759 } |
|
1760 |
|
1761 CBTLocalAddressFetcher::CBTLocalAddressFetcher(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry, TInt aPriority) |
|
1762 : CActive(aPriority), |
|
1763 iBURMgr(aBURMgr), |
|
1764 iRegistry(aRegistry) |
|
1765 { |
|
1766 LOG_FUNC |
|
1767 |
|
1768 CActiveScheduler::Add(this); |
|
1769 } |
|
1770 |
|
1771 CBTLocalAddressFetcher::~CBTLocalAddressFetcher() |
|
1772 { |
|
1773 LOG_FUNC |
|
1774 |
|
1775 // Cancel any outstanding requests |
|
1776 Cancel(); |
|
1777 iProperty.Close(); |
|
1778 } |
|
1779 |
|
1780 void CBTLocalAddressFetcher::ConstructL() |
|
1781 { |
|
1782 LOG_FUNC |
|
1783 |
|
1784 // Attach to KPropertyKeyBluetoothGetLocalDeviceAddress |
|
1785 LEAVEIFERRORL(iProperty.Attach(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothGetLocalDeviceAddress)); |
|
1786 } |
|
1787 |
|
1788 void CBTLocalAddressFetcher::FetchLocalAddress() |
|
1789 { |
|
1790 LOG_FUNC |
|
1791 |
|
1792 // Subscribe for local address, in case we need to wait |
|
1793 SubscribeToGetLocalDeviceAddressKey(); |
|
1794 |
|
1795 // Attempt to read the BT address from KPropertyKeyBluetoothGetLocalDeviceAddress key |
|
1796 // If key is not found or yields a zero address then try the registry. |
|
1797 // If the registry also holds a zero address then wait for notification from the P&S key. |
|
1798 TBuf8<KBTDevAddrSize> btAddrDes; |
|
1799 TBTDevAddr btAddr; |
|
1800 TInt err = iProperty.Get(btAddrDes); |
|
1801 |
|
1802 if (err != KErrNone) |
|
1803 { |
|
1804 // Key does not exist or could not be read. |
|
1805 // Stack may not be loaded, so now try registry. |
|
1806 // Ignore any errors; if we can't read this now then we will wait for the stack. |
|
1807 TRAP_IGNORE(btAddr = GetLocalAddressFromRegistryL()); |
|
1808 } |
|
1809 else |
|
1810 { |
|
1811 // Convert btAddrDes to TBTDevAddr if it has the required size. |
|
1812 if (btAddrDes.Length() == KBTDevAddrSize) |
|
1813 { |
|
1814 btAddr = btAddrDes; |
|
1815 } |
|
1816 |
|
1817 if (btAddr == TBTDevAddr()) |
|
1818 { |
|
1819 // Key exists, so stack is loaded, but address is zero, so now try registry |
|
1820 // Ignore any errors; if we can't read this now then we will wait for the stack. |
|
1821 TRAP_IGNORE(btAddr = GetLocalAddressFromRegistryL()); |
|
1822 } |
|
1823 } |
|
1824 |
|
1825 // We have tried our best to get the local address. |
|
1826 // If this is non-zero, provide to CBTManServerBURMgr instance. |
|
1827 // Otherwise, wait on P&S key |
|
1828 if (btAddr != TBTDevAddr()) |
|
1829 { |
|
1830 // We have a non-zero address. |
|
1831 // Cancel subscription and inform CBTManServerBURMgr. |
|
1832 Cancel(); |
|
1833 iBURMgr.SetLocalAddress(btAddr); |
|
1834 } |
|
1835 } |
|
1836 |
|
1837 void CBTLocalAddressFetcher::SubscribeToGetLocalDeviceAddressKey() |
|
1838 { |
|
1839 LOG_FUNC |
|
1840 |
|
1841 // Subscribe to KPropertyKeyBluetoothGetLocalDeviceAddress key |
|
1842 iProperty.Subscribe(iStatus); |
|
1843 SetActive(); |
|
1844 } |
|
1845 |
|
1846 TBTDevAddr CBTLocalAddressFetcher::GetLocalAddressFromRegistryL() |
|
1847 { |
|
1848 LOG_FUNC |
|
1849 |
|
1850 TBTLocalDevice* regLocalDevice=iRegistry.GetLocalDeviceL(); |
|
1851 TBTDevAddr result=regLocalDevice->Address(); |
|
1852 delete regLocalDevice; |
|
1853 |
|
1854 return result; |
|
1855 } |
|
1856 |
|
1857 void CBTLocalAddressFetcher::RunL() |
|
1858 { |
|
1859 LOG_FUNC |
|
1860 |
|
1861 if (iStatus == KErrNone) |
|
1862 { |
|
1863 // Obtain address and send to CBTManServerBURMgr |
|
1864 TBuf8<KBTDevAddrSize> btAddrDes; |
|
1865 TBTDevAddr btAddr; |
|
1866 TInt err = iProperty.Get(btAddrDes); |
|
1867 |
|
1868 __ASSERT_DEBUG(err == KErrNone, PANIC(KBTBackupPanicCat, EBTBURMgrUnexpectedRPropertyError)); |
|
1869 |
|
1870 if (err == KErrNone) |
|
1871 { |
|
1872 btAddr = btAddrDes; |
|
1873 iBURMgr.SetLocalAddress(btAddr); |
|
1874 } |
|
1875 } |
|
1876 } |
|
1877 |
|
1878 void CBTLocalAddressFetcher::DoCancel() |
|
1879 { |
|
1880 LOG_FUNC |
|
1881 |
|
1882 // Cancel our subscription |
|
1883 iProperty.Cancel(); |
|
1884 } |
|
1885 |
|
1886 /** |
|
1887 CBTActiveBackupDataClient - Active callback implementation (for restore notification) |
|
1888 **/ |
|
1889 CBTActiveBackupDataClient* CBTActiveBackupDataClient::NewL(CBTManServerBURMgr& aBURMgr) |
|
1890 { |
|
1891 LOG_STATIC_FUNC |
|
1892 |
|
1893 CBTActiveBackupDataClient* result = new (ELeave) CBTActiveBackupDataClient(aBURMgr); |
|
1894 return result; |
|
1895 } |
|
1896 |
|
1897 CBTActiveBackupDataClient::CBTActiveBackupDataClient(CBTManServerBURMgr& aBURMgr) |
|
1898 : iBURMgr(aBURMgr) |
|
1899 { |
|
1900 LOG_FUNC |
|
1901 } |
|
1902 |
|
1903 CBTActiveBackupDataClient::~CBTActiveBackupDataClient() |
|
1904 { |
|
1905 LOG_FUNC |
|
1906 } |
|
1907 |
|
1908 // Backup methods (not used) |
|
1909 void CBTActiveBackupDataClient::AllSnapshotsSuppliedL() |
|
1910 { |
|
1911 LOG_FUNC |
|
1912 |
|
1913 //Not supported |
|
1914 User::Leave(KErrNotSupported); |
|
1915 } |
|
1916 |
|
1917 void CBTActiveBackupDataClient::ReceiveSnapshotDataL(TDriveNumber /*aDrive*/, TDesC8& /*aBuffer*/, TBool /*aLastSection*/) |
|
1918 { |
|
1919 LOG_FUNC |
|
1920 |
|
1921 //Not supported |
|
1922 User::Leave(KErrNotSupported); |
|
1923 } |
|
1924 |
|
1925 TUint CBTActiveBackupDataClient::GetExpectedDataSize(TDriveNumber /*aDrive*/) |
|
1926 { |
|
1927 LOG_FUNC |
|
1928 |
|
1929 //Not supported - so expected size can be 0 |
|
1930 return 0; |
|
1931 } |
|
1932 |
|
1933 void CBTActiveBackupDataClient::GetSnapshotDataL(TDriveNumber /*aDrive*/, TPtr8& /*aBuffer*/, TBool& /*aFinished*/) |
|
1934 { |
|
1935 LOG_FUNC |
|
1936 |
|
1937 //Not supported |
|
1938 User::Leave(KErrNotSupported); |
|
1939 } |
|
1940 |
|
1941 void CBTActiveBackupDataClient::InitialiseGetBackupDataL(TDriveNumber /*aDrive*/) |
|
1942 { |
|
1943 LOG_FUNC |
|
1944 |
|
1945 //Not supported |
|
1946 User::Leave(KErrNotSupported); |
|
1947 } |
|
1948 |
|
1949 void CBTActiveBackupDataClient::GetBackupDataSectionL(TPtr8& /*aBuffer*/, TBool& /*aFinished*/) |
|
1950 { |
|
1951 LOG_FUNC |
|
1952 |
|
1953 //Not supported |
|
1954 User::Leave(KErrNotSupported); |
|
1955 } |
|
1956 |
|
1957 //Restore methods (only the notification method RestoreComplete() is used) |
|
1958 |
|
1959 void CBTActiveBackupDataClient::InitialiseRestoreBaseDataL(TDriveNumber /*aDrive*/) |
|
1960 { |
|
1961 LOG_FUNC |
|
1962 |
|
1963 //Note that we are doing a base restore. |
|
1964 User::Leave(KErrNotSupported); |
|
1965 } |
|
1966 |
|
1967 void CBTActiveBackupDataClient::RestoreBaseDataSectionL(TDesC8& /*aBuffer*/, TBool /*aFinished*/) |
|
1968 { |
|
1969 LOG_FUNC |
|
1970 |
|
1971 //Not supported |
|
1972 User::Leave(KErrNotSupported); |
|
1973 } |
|
1974 |
|
1975 void CBTActiveBackupDataClient::InitialiseRestoreIncrementDataL(TDriveNumber /*aDrive*/) |
|
1976 { |
|
1977 LOG_FUNC |
|
1978 |
|
1979 //Not supported |
|
1980 User::Leave(KErrNotSupported); |
|
1981 } |
|
1982 |
|
1983 void CBTActiveBackupDataClient::RestoreIncrementDataSectionL(TDesC8& /*aBuffer*/, TBool /*aFinished*/) |
|
1984 { |
|
1985 LOG_FUNC |
|
1986 |
|
1987 //Not supported |
|
1988 User::Leave(KErrNotSupported); |
|
1989 } |
|
1990 |
|
1991 void CBTActiveBackupDataClient::RestoreComplete(TDriveNumber aDrive) |
|
1992 { |
|
1993 LOG_FUNC |
|
1994 |
|
1995 // Allow CBTManServerBURMgr instance to handle arrival of restore file. |
|
1996 if (aDrive == RFs::GetSystemDrive()) |
|
1997 { |
|
1998 iBURMgr.RestoreFileReady(); |
|
1999 } |
|
2000 } |
|
2001 |
|
2002 |
|
2003 //General methods |
|
2004 |
|
2005 void CBTActiveBackupDataClient::TerminateMultiStageOperation() |
|
2006 { |
|
2007 LOG_FUNC |
|
2008 |
|
2009 //Dont care - we will see the operation is cancelled when normal or unset mode is invoked. |
|
2010 } |
|
2011 |
|
2012 //Test methods |
|
2013 |
|
2014 TUint CBTActiveBackupDataClient::GetDataChecksum(TDriveNumber /*aDrive*/) |
|
2015 { |
|
2016 LOG_FUNC |
|
2017 |
|
2018 //Return an invariant checksum |
|
2019 return 0; |
|
2020 } |