1 /* |
|
2 * Copyright (c) 2008 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: Context publishing helper dll |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <cfcontextobject.h> |
|
20 #include <cfclient.h> |
|
21 #include <mdesession.h> |
|
22 #include <mdeobject.h> |
|
23 #include <s32mem.h> |
|
24 #include <MVPbkContactLink.h> |
|
25 #include <MVPbkStoreContact.h> |
|
26 #include <MVPbkStreamable.h> |
|
27 #include <CVPbkContactLinkArray.h> |
|
28 #include <e32debug.h> |
|
29 #include <w32std.h> |
|
30 #include "hgcontextutilityimpl.h" |
|
31 #include "hgcontexttypes.h" |
|
32 |
|
33 // max number of entries processed when aContextData is an array in PublishContextL |
|
34 const TInt KMaxEntriesInMulti = 20; |
|
35 |
|
36 // separator character in combined string for multiple entries |
|
37 const TInt KMultiSepChar = 0x0001; |
|
38 |
|
39 // granularity for string array |
|
40 const TInt KArrayGranularity = 4; |
|
41 |
|
42 // argument for CBufFlat ctor when serializing contact links |
|
43 const TInt KBufGranularity = 64; |
|
44 |
|
45 // default security policy (use LocalServices cap) for contexts |
|
46 _LIT_SECURITY_POLICY_C1( KContextSecurity, ECapabilityLocalServices ); |
|
47 |
|
48 // ----------------------------------------------------------------------------- |
|
49 // CHgContextUtilityImpl::NewL |
|
50 // ----------------------------------------------------------------------------- |
|
51 // |
|
52 CHgContextUtilityImpl* CHgContextUtilityImpl::NewL() |
|
53 { |
|
54 CHgContextUtilityImpl* self = NewLC(); |
|
55 CleanupStack::Pop( self ); |
|
56 return self; |
|
57 } |
|
58 |
|
59 // ----------------------------------------------------------------------------- |
|
60 // CHgContextUtilityImpl::NewLC |
|
61 // ----------------------------------------------------------------------------- |
|
62 // |
|
63 CHgContextUtilityImpl* CHgContextUtilityImpl::NewLC() |
|
64 { |
|
65 CHgContextUtilityImpl* self = new ( ELeave ) CHgContextUtilityImpl; |
|
66 CleanupStack::PushL( self ); |
|
67 self->ConstructL(); |
|
68 return self; |
|
69 } |
|
70 |
|
71 // ----------------------------------------------------------------------------- |
|
72 // CHgContextUtilityImpl::CHgContextUtilityImpl |
|
73 // ----------------------------------------------------------------------------- |
|
74 // |
|
75 CHgContextUtilityImpl::CHgContextUtilityImpl() |
|
76 : CTimer( CActive::EPriorityStandard ) |
|
77 { |
|
78 CActiveScheduler::Add( this ); |
|
79 } |
|
80 |
|
81 // ----------------------------------------------------------------------------- |
|
82 // CHgContextUtilityImpl::ConstructL |
|
83 // ----------------------------------------------------------------------------- |
|
84 // |
|
85 void CHgContextUtilityImpl::ConstructL() |
|
86 { |
|
87 CTimer::ConstructL(); |
|
88 |
|
89 iEnv = CCoeEnv::Static(); // may be NULL |
|
90 |
|
91 // Do not create iCFClient here as cf server may not be available yet |
|
92 // if we are early in the boot phase. |
|
93 |
|
94 // set defaults |
|
95 RePublishWhenFgL( EFalse ); |
|
96 AllowPublishFromBackground( EFalse ); |
|
97 } |
|
98 |
|
99 // ----------------------------------------------------------------------------- |
|
100 // CHgContextUtilityImpl::~CHgContextUtilityImpl |
|
101 // ----------------------------------------------------------------------------- |
|
102 // |
|
103 CHgContextUtilityImpl::~CHgContextUtilityImpl() |
|
104 { |
|
105 Cancel(); |
|
106 delete iPendingContextType; |
|
107 delete iPendingContextData; |
|
108 delete iPendingContextDataArray; |
|
109 delete iCFClient; |
|
110 delete iLastContextType; |
|
111 delete iLastContextData; |
|
112 if ( iFgWatchEnabled && iEnv ) |
|
113 { |
|
114 iEnv->RemoveForegroundObserver( *this ); |
|
115 } |
|
116 |
|
117 iMusicContextInfo.ResetAndDestroy(); |
|
118 } |
|
119 |
|
120 // ----------------------------------------------------------------------------- |
|
121 // CHgContextUtilityImpl::CFReady |
|
122 // ----------------------------------------------------------------------------- |
|
123 // |
|
124 TBool CHgContextUtilityImpl::CFReady() |
|
125 { |
|
126 if ( !iCFClient ) |
|
127 { |
|
128 TRAPD( err, iCFClient = CCFClient::NewL( *this ) ); |
|
129 if ( err != KErrNone ) |
|
130 { |
|
131 RDebug::Printf( "[hgctxutil] cfw not ready" ); |
|
132 return EFalse; |
|
133 } |
|
134 } |
|
135 return ETrue; |
|
136 } |
|
137 |
|
138 // ----------------------------------------------------------------------------- |
|
139 // CHgContextUtilityImpl::PublishContextL |
|
140 // All other non-static versions of this function will fall back to this one. |
|
141 // ----------------------------------------------------------------------------- |
|
142 // |
|
143 void CHgContextUtilityImpl::PublishContextL( const TDesC& aContextType, |
|
144 const TDesC& aContextData ) |
|
145 { |
|
146 RDebug::Print( _L("[hgctxutil] PublishContextL [%S] [%S]"), |
|
147 &aContextType, &aContextData ); |
|
148 // create cf client instance if not yet done |
|
149 // and check foreground status if needed |
|
150 if ( CFReady() && AllowedToPublish() ) |
|
151 { |
|
152 // call static version with our cf client instance |
|
153 PublishContextL( *iCFClient, aContextType, aContextData ); |
|
154 } |
|
155 // store type and value for later use |
|
156 // (even when cfserver is not available yet, the data may still be |
|
157 // used later when the app comes to foreground, for example) |
|
158 if ( iLastContextType != &aContextType ) |
|
159 { |
|
160 delete iLastContextType; iLastContextType = 0; |
|
161 iLastContextType = aContextType.AllocL(); |
|
162 } |
|
163 if ( iLastContextData != &aContextData ) |
|
164 { |
|
165 delete iLastContextData; iLastContextData = 0; |
|
166 iLastContextData = aContextData.AllocL(); |
|
167 } |
|
168 } |
|
169 |
|
170 // ----------------------------------------------------------------------------- |
|
171 // AppendCharL |
|
172 // Appends a char to aDst, calls ReAllocL when needed, assumes that aDst |
|
173 // is also on cleanupstack (at top position) so it updates that pointer too. |
|
174 // ----------------------------------------------------------------------------- |
|
175 // |
|
176 LOCAL_C void AppendCharL( HBufC*& aDst, TChar aChar ) |
|
177 { |
|
178 TPtr des( aDst->Des() ); |
|
179 if ( des.Length() == des.MaxLength() ) |
|
180 { |
|
181 HBufC* oldDst = aDst; |
|
182 aDst = aDst->ReAllocL( des.MaxLength() * 2 ); |
|
183 CleanupStack::Pop( oldDst ); // pop the old pointer |
|
184 CleanupStack::PushL( aDst ); // and push the new (possibly different) one |
|
185 des.Set( aDst->Des() ); |
|
186 } |
|
187 des.Append( aChar ); |
|
188 } |
|
189 |
|
190 // ----------------------------------------------------------------------------- |
|
191 // CHgContextUtilityImpl::BuildCombinedStringL |
|
192 // ----------------------------------------------------------------------------- |
|
193 // |
|
194 HBufC* CHgContextUtilityImpl::BuildCombinedStringL( |
|
195 const MDesCArray& aArray ) |
|
196 { |
|
197 TInt arrayCount = aArray.MdcaCount(); |
|
198 if ( arrayCount >= 2 ) |
|
199 { |
|
200 // Rules: |
|
201 // 1. escape all separator chars in the input with a preceeding \ |
|
202 // 2. escape all \ chars in the input with \\ |
|
203 // 3. take only the first KMaxEntriesInMulti elements from the array |
|
204 // 4. append a separator also after last entry |
|
205 // 5. prepend two separators to the combined string |
|
206 TInt processedEntryCount = Min( arrayCount, KMaxEntriesInMulti ); |
|
207 // calculate a big enough size so we can avoid ReAllocL calls later |
|
208 TInt sz = 0; |
|
209 for ( TInt i = 0; i < processedEntryCount; ++i ) |
|
210 { |
|
211 sz += aArray.MdcaPoint( i ).Length() + 1; |
|
212 } |
|
213 sz += 2; // for the magic prefix |
|
214 HBufC* value = HBufC::NewLC( sz ); |
|
215 AppendCharL( value, KMultiSepChar ); |
|
216 AppendCharL( value, KMultiSepChar ); |
|
217 for ( TInt i = 0; i < processedEntryCount; ++i ) |
|
218 { |
|
219 TPtrC entry( aArray.MdcaPoint( i ) ); |
|
220 // append, also do the escaping |
|
221 for ( TInt j = 0, je = entry.Length(); j != je; ++j ) |
|
222 { |
|
223 TChar c = entry[j]; |
|
224 if ( c == KMultiSepChar || c == '\\' ) |
|
225 { |
|
226 AppendCharL( value, '\\' ); |
|
227 } |
|
228 AppendCharL( value, c ); |
|
229 } |
|
230 AppendCharL( value, KMultiSepChar ); |
|
231 } |
|
232 CleanupStack::Pop( value ); |
|
233 return value; |
|
234 } |
|
235 return 0; |
|
236 } |
|
237 |
|
238 // ----------------------------------------------------------------------------- |
|
239 // CHgContextUtilityImpl::SplitCombinedStringL |
|
240 // ----------------------------------------------------------------------------- |
|
241 // |
|
242 void CHgContextUtilityImpl::SplitCombinedStringL( |
|
243 const TDesC& aString, CDesCArray& aArray ) |
|
244 { |
|
245 TInt inputLength = aString.Length(); |
|
246 TBool isMulti = inputLength > 2 |
|
247 && aString[0] == KMultiSepChar && aString[1] == KMultiSepChar; |
|
248 if ( isMulti ) |
|
249 { |
|
250 // allocate a work buffer that is big enough for sure |
|
251 HBufC* buf = HBufC::NewLC( inputLength ); |
|
252 TPtr des( buf->Des() ); |
|
253 TBool esc = EFalse; |
|
254 // go through the string, find entries, and add them to output array |
|
255 for ( TInt i = 2; i < inputLength; ++i ) // start from 2 because of the magic prefix |
|
256 { |
|
257 TChar c = aString[i]; |
|
258 if ( c == '\\' && !esc ) |
|
259 { |
|
260 esc = ETrue; |
|
261 } |
|
262 else if ( c == KMultiSepChar && !esc ) |
|
263 { |
|
264 // found separator: append to output array, clear buffer, and continue |
|
265 aArray.AppendL( des ); |
|
266 des.Zero(); |
|
267 } |
|
268 else |
|
269 { |
|
270 esc = EFalse; |
|
271 des.Append( c ); |
|
272 } |
|
273 } |
|
274 CleanupStack::PopAndDestroy( buf ); |
|
275 } |
|
276 else |
|
277 { |
|
278 // not a combined string: append to array as it is |
|
279 aArray.AppendL( aString ); |
|
280 } |
|
281 } |
|
282 |
|
283 // ----------------------------------------------------------------------------- |
|
284 // CHgContextUtilityImpl::PublishContextL |
|
285 // ----------------------------------------------------------------------------- |
|
286 // |
|
287 void CHgContextUtilityImpl::PublishContextL( const TDesC& aContextType, |
|
288 const MDesCArray& aContextData ) |
|
289 { |
|
290 TInt entryCount = aContextData.MdcaCount(); |
|
291 // do nothing if array is empty |
|
292 if ( !entryCount ) |
|
293 { |
|
294 return; |
|
295 } |
|
296 // nothing special when having only 1 item |
|
297 if ( entryCount == 1 ) |
|
298 { |
|
299 PublishContextL( aContextType, aContextData.MdcaPoint( 0 ) ); |
|
300 return; |
|
301 } |
|
302 // at least two items: create the special combined string |
|
303 HBufC* value = BuildCombinedStringL( aContextData ); |
|
304 CleanupStack::PushL( value ); |
|
305 // publish the combined string |
|
306 PublishContextL( aContextType, *value ); |
|
307 CleanupStack::PopAndDestroy( value ); |
|
308 } |
|
309 |
|
310 // ----------------------------------------------------------------------------- |
|
311 // CHgContextUtilityImpl::PublishContextL |
|
312 // This is the version of the function where the real work is performed. |
|
313 // ----------------------------------------------------------------------------- |
|
314 // |
|
315 void CHgContextUtilityImpl::PublishContextL( CCFClient& aCFClient, |
|
316 const TDesC& aContextType, const TDesC& aContextData ) |
|
317 { |
|
318 CCFContextObject* context = CCFContextObject::NewLC(); |
|
319 context->SetSourceL( KHgCFSource ); |
|
320 context->SetTypeL( aContextType ); |
|
321 context->SetValueL( aContextData ); |
|
322 TInt err = aCFClient.PublishContext( *context ); |
|
323 if ( err == KErrNotFound ) |
|
324 { |
|
325 User::LeaveIfError( aCFClient.DefineContext( KHgCFSource, |
|
326 aContextType, KContextSecurity ) ); |
|
327 err = aCFClient.PublishContext( *context ); |
|
328 if ( err != KErrArgument ) // ignore -6 which comes e.g. when trying to publish an empty value |
|
329 { |
|
330 User::LeaveIfError( err ); |
|
331 } |
|
332 } |
|
333 else if ( err != KErrArgument ) |
|
334 { |
|
335 User::LeaveIfError( err ); |
|
336 } |
|
337 CleanupStack::PopAndDestroy( context ); |
|
338 } |
|
339 |
|
340 // ----------------------------------------------------------------------------- |
|
341 // CHgContextUtilityImpl::GetContextL |
|
342 // ----------------------------------------------------------------------------- |
|
343 // |
|
344 HBufC* CHgContextUtilityImpl::GetContextL( const TDesC& aContextSource, |
|
345 const TDesC& aContextType ) |
|
346 { |
|
347 HBufC* ret = 0; |
|
348 if ( CFReady() ) |
|
349 { |
|
350 CCFContextQuery* query = CCFContextQuery::NewLC(); |
|
351 query->SetSourceL( aContextSource ); |
|
352 query->SetTypeL( aContextType ); |
|
353 RContextObjectArray result; |
|
354 TInt err = iCFClient->RequestContext( *query, result ); |
|
355 if ( err == KErrNone && result.Count() ) |
|
356 { |
|
357 ret = result[0]->Value().Alloc(); |
|
358 } |
|
359 result.ResetAndDestroy(); |
|
360 CleanupStack::PopAndDestroy( query ); |
|
361 } |
|
362 return ret; |
|
363 } |
|
364 |
|
365 // ----------------------------------------------------------------------------- |
|
366 // CHgContextUtilityImpl::GetContextL |
|
367 // ----------------------------------------------------------------------------- |
|
368 // |
|
369 HBufC* CHgContextUtilityImpl::GetContextL( const TDesC& aContextType ) |
|
370 { |
|
371 return GetContextL( KHgCFSource, aContextType ); |
|
372 } |
|
373 |
|
374 // ----------------------------------------------------------------------------- |
|
375 // CHgContextUtilityImpl::PublishContextDelayedL |
|
376 // ----------------------------------------------------------------------------- |
|
377 // |
|
378 void CHgContextUtilityImpl::PublishContextDelayedL( const TDesC& aContextType, |
|
379 const TDesC& aContextData, TTimeIntervalMicroSeconds32 aDelay ) |
|
380 { |
|
381 Cancel(); |
|
382 delete iPendingContextType; iPendingContextType = 0; |
|
383 iPendingContextType = aContextType.AllocL(); |
|
384 delete iPendingContextData; iPendingContextData = 0; |
|
385 iPendingContextData = aContextData.AllocL(); |
|
386 delete iPendingContextDataArray; iPendingContextDataArray = 0; |
|
387 After( aDelay ); |
|
388 } |
|
389 |
|
390 // ----------------------------------------------------------------------------- |
|
391 // CHgContextUtilityImpl::PublishContextDelayedL |
|
392 // ----------------------------------------------------------------------------- |
|
393 // |
|
394 void CHgContextUtilityImpl::PublishContextDelayedL( const TDesC& aContextType, |
|
395 const MDesCArray& aContextData, TTimeIntervalMicroSeconds32 aDelay ) |
|
396 { |
|
397 Cancel(); |
|
398 delete iPendingContextType; iPendingContextType = 0; |
|
399 iPendingContextType = aContextType.AllocL(); |
|
400 delete iPendingContextData; iPendingContextData = 0; |
|
401 if ( iPendingContextDataArray ) |
|
402 { |
|
403 iPendingContextDataArray->Reset(); |
|
404 } |
|
405 else |
|
406 { |
|
407 iPendingContextDataArray = new ( ELeave ) CDesC16ArrayFlat( KArrayGranularity ); |
|
408 } |
|
409 for ( TInt i = 0, ie = aContextData.MdcaCount(); i != ie; ++i ) |
|
410 { |
|
411 iPendingContextDataArray->AppendL( aContextData.MdcaPoint( i ) ); |
|
412 } |
|
413 After( aDelay ); |
|
414 } |
|
415 |
|
416 // ----------------------------------------------------------------------------- |
|
417 // CHgContextUtilityImpl::RunL |
|
418 // ----------------------------------------------------------------------------- |
|
419 // |
|
420 void CHgContextUtilityImpl::RunL() |
|
421 { |
|
422 if ( iPendingContextType ) |
|
423 { |
|
424 if ( iPendingContextData ) |
|
425 { |
|
426 PublishContextL( *iPendingContextType, *iPendingContextData ); |
|
427 } |
|
428 else if ( iPendingContextDataArray ) |
|
429 { |
|
430 PublishContextL( *iPendingContextType, *iPendingContextDataArray ); |
|
431 } |
|
432 } |
|
433 } |
|
434 |
|
435 // ----------------------------------------------------------------------------- |
|
436 // CHgContextUtilityImpl::RunError |
|
437 // ----------------------------------------------------------------------------- |
|
438 // |
|
439 TInt CHgContextUtilityImpl::RunError( TInt /*aError*/ ) |
|
440 { |
|
441 return KErrNone; |
|
442 } |
|
443 |
|
444 // empty implementations for cfw |
|
445 |
|
446 // ----------------------------------------------------------------------------- |
|
447 // CHgContextUtilityImpl::ContextIndicationL |
|
448 // ----------------------------------------------------------------------------- |
|
449 // |
|
450 void CHgContextUtilityImpl::ContextIndicationL( |
|
451 const CCFContextIndication& /*aChangedContext*/ ) |
|
452 { |
|
453 // empty |
|
454 } |
|
455 |
|
456 // ----------------------------------------------------------------------------- |
|
457 // CHgContextUtilityImpl::ActionIndicationL |
|
458 // ----------------------------------------------------------------------------- |
|
459 // |
|
460 void CHgContextUtilityImpl::ActionIndicationL( |
|
461 const CCFActionIndication& /*aActionToExecute*/ ) |
|
462 { |
|
463 // empty |
|
464 } |
|
465 |
|
466 // ----------------------------------------------------------------------------- |
|
467 // CHgContextUtilityImpl::HandleContextFrameworkError |
|
468 // ----------------------------------------------------------------------------- |
|
469 // |
|
470 void CHgContextUtilityImpl::HandleContextFrameworkError( TCFError /*aError*/, |
|
471 const TDesC& /*aSource*/, |
|
472 const TDesC& /*aType*/ ) |
|
473 { |
|
474 // empty |
|
475 } |
|
476 |
|
477 // ----------------------------------------------------------------------------- |
|
478 // CHgContextUtilityImpl::Extension |
|
479 // ----------------------------------------------------------------------------- |
|
480 // |
|
481 TAny* CHgContextUtilityImpl::Extension( const TUid& /*aExtensionUid*/ ) const |
|
482 { |
|
483 return 0; |
|
484 } |
|
485 |
|
486 // ----------------------------------------------------------------------------- |
|
487 // CHgContextUtilityImpl::MakeLinkPublishableLC |
|
488 // ----------------------------------------------------------------------------- |
|
489 // |
|
490 HBufC* CHgContextUtilityImpl::MakeLinkPublishableLC( |
|
491 const MVPbkContactLink& aLink ) |
|
492 { |
|
493 HBufC* ret = 0; |
|
494 // serialize the link and place it into a 16-bit descriptor |
|
495 // prefixed with one special mark character |
|
496 const MVPbkStreamable* strm = aLink.Streamable(); |
|
497 User::LeaveIfNull(strm); |
|
498 CBufFlat* buf = CBufFlat::NewL( KBufGranularity ); |
|
499 CleanupStack::PushL( buf ); |
|
500 RBufWriteStream ws; |
|
501 CleanupClosePushL( ws ); |
|
502 ws.Open( *buf ); |
|
503 strm->ExternalizeL( ws ); |
|
504 CleanupStack::PopAndDestroy( &ws ); |
|
505 TPtr8 p( buf->Ptr( 0 ) ); |
|
506 ret = HBufC::NewLC( p.Length() + 1 ); |
|
507 TPtr des( ret->Des() ); |
|
508 des.Copy( p ); |
|
509 _LIT( KTemp, " " ); |
|
510 des.Insert( 0, KTemp ); |
|
511 des[0] = KHgCFValueLinkMarker; // codescanner::accessArrayElementWithoutCheck2 |
|
512 CleanupStack::Pop( ret ); |
|
513 CleanupStack::PopAndDestroy( buf ); |
|
514 CleanupStack::PushL( ret ); |
|
515 return ret; |
|
516 } |
|
517 |
|
518 // ----------------------------------------------------------------------------- |
|
519 // CHgContextUtilityImpl::PublishContactContextL |
|
520 // ----------------------------------------------------------------------------- |
|
521 // |
|
522 void CHgContextUtilityImpl::PublishContactContextL( |
|
523 const MVPbkStoreContact& aContact, |
|
524 const TTimeIntervalMicroSeconds32& aDelay ) |
|
525 { |
|
526 MVPbkContactLink* link = aContact.CreateLinkLC(); |
|
527 if ( link ) |
|
528 { |
|
529 HBufC* pubstr = MakeLinkPublishableLC( *link ); |
|
530 PublishContactContextL( *pubstr, aDelay ); |
|
531 CleanupStack::PopAndDestroy( pubstr ); |
|
532 } |
|
533 CleanupStack::PopAndDestroy( );//link |
|
534 } |
|
535 |
|
536 // ----------------------------------------------------------------------------- |
|
537 // CHgContextUtilityImpl::PublishContactContextL |
|
538 // ----------------------------------------------------------------------------- |
|
539 // |
|
540 void CHgContextUtilityImpl::PublishContactContextL( |
|
541 const MVPbkContactLink& aContactLink, |
|
542 const TTimeIntervalMicroSeconds32& aDelay ) |
|
543 { |
|
544 HBufC* pubstr = MakeLinkPublishableLC( aContactLink ); |
|
545 PublishContactContextL( *pubstr, aDelay ); |
|
546 CleanupStack::PopAndDestroy( pubstr ); |
|
547 } |
|
548 |
|
549 // ----------------------------------------------------------------------------- |
|
550 // CHgContextUtilityImpl::PublishContactContextL |
|
551 // ----------------------------------------------------------------------------- |
|
552 // |
|
553 void CHgContextUtilityImpl::PublishContactContextL( |
|
554 const TDesC& aContactName, |
|
555 const TTimeIntervalMicroSeconds32& aDelay ) |
|
556 { |
|
557 if ( !aDelay.Int() ) |
|
558 { |
|
559 PublishContextL( KHgCFTypeContact, aContactName ); |
|
560 } |
|
561 else |
|
562 { |
|
563 PublishContextDelayedL( KHgCFTypeContact, aContactName, aDelay ); |
|
564 } |
|
565 } |
|
566 |
|
567 // ----------------------------------------------------------------------------- |
|
568 // CHgContextUtilityImpl::PublishContactContextL |
|
569 // ----------------------------------------------------------------------------- |
|
570 // |
|
571 void CHgContextUtilityImpl::PublishContactContextL( |
|
572 const RPointerArray<MVPbkStoreContact>& aContacts, |
|
573 const TTimeIntervalMicroSeconds32& aDelay ) |
|
574 { |
|
575 CDesCArray* arr = new ( ELeave ) CDesCArrayFlat( KArrayGranularity ); |
|
576 CleanupStack::PushL( arr ); |
|
577 for ( TInt i = 0, ie = aContacts.Count(); i != ie; ++i ) |
|
578 { |
|
579 MVPbkContactLink* link = aContacts[i]->CreateLinkLC(); |
|
580 if ( link ) |
|
581 { |
|
582 HBufC* pubstr = MakeLinkPublishableLC( *link ); |
|
583 arr->AppendL( *pubstr ); |
|
584 CleanupStack::PopAndDestroy( pubstr ); |
|
585 } |
|
586 CleanupStack::PopAndDestroy( );//link |
|
587 } |
|
588 PublishContactContextL( *arr, aDelay ); |
|
589 CleanupStack::PopAndDestroy( arr ); |
|
590 } |
|
591 |
|
592 // ----------------------------------------------------------------------------- |
|
593 // CHgContextUtilityImpl::PublishContactContextL |
|
594 // ----------------------------------------------------------------------------- |
|
595 // |
|
596 void CHgContextUtilityImpl::PublishContactContextL( |
|
597 const CVPbkContactLinkArray& aContactLinks, |
|
598 const TTimeIntervalMicroSeconds32& aDelay ) |
|
599 { |
|
600 CDesCArray* arr = new ( ELeave ) CDesCArrayFlat( KArrayGranularity ); |
|
601 CleanupStack::PushL( arr ); |
|
602 for ( TInt i = 0, ie = aContactLinks.Count(); i != ie; ++i ) |
|
603 { |
|
604 HBufC* pubstr = MakeLinkPublishableLC( aContactLinks.At( i ) ); |
|
605 arr->AppendL( *pubstr ); |
|
606 CleanupStack::PopAndDestroy( pubstr ); |
|
607 } |
|
608 PublishContactContextL( *arr, aDelay ); |
|
609 CleanupStack::PopAndDestroy( arr ); |
|
610 } |
|
611 |
|
612 // ----------------------------------------------------------------------------- |
|
613 // CHgContextUtilityImpl::PublishContactContextL |
|
614 // ----------------------------------------------------------------------------- |
|
615 // |
|
616 void CHgContextUtilityImpl::PublishContactContextL( |
|
617 const MDesCArray& aContactNames, |
|
618 const TTimeIntervalMicroSeconds32& aDelay ) |
|
619 { |
|
620 if ( !aDelay.Int() ) |
|
621 { |
|
622 PublishContextL( KHgCFTypeContact, aContactNames ); |
|
623 } |
|
624 else |
|
625 { |
|
626 PublishContextDelayedL( KHgCFTypeContact, aContactNames, aDelay ); |
|
627 } |
|
628 } |
|
629 |
|
630 // ----------------------------------------------------------------------------- |
|
631 // CHgContextUtilityImpl::PublishTextContextL |
|
632 // ----------------------------------------------------------------------------- |
|
633 // |
|
634 void CHgContextUtilityImpl::PublishTextContextL( const TDesC& aText, |
|
635 const TTimeIntervalMicroSeconds32& aDelay ) |
|
636 { |
|
637 if ( !aDelay.Int() ) |
|
638 { |
|
639 PublishContextL( KHgCFTypeText, aText ); |
|
640 } |
|
641 else |
|
642 { |
|
643 PublishContextDelayedL( KHgCFTypeText, aText, aDelay ); |
|
644 } |
|
645 } |
|
646 |
|
647 // ----------------------------------------------------------------------------- |
|
648 // CHgContextUtilityImpl::PublishUrlContextL |
|
649 // ----------------------------------------------------------------------------- |
|
650 // |
|
651 void CHgContextUtilityImpl::PublishUrlContextL( const TDesC& aUrl, |
|
652 const TTimeIntervalMicroSeconds32& aDelay ) |
|
653 { |
|
654 if ( !aDelay.Int() ) |
|
655 { |
|
656 PublishContextL( KHgCFTypeUrl, aUrl ); |
|
657 } |
|
658 else |
|
659 { |
|
660 PublishContextDelayedL( KHgCFTypeUrl, aUrl, aDelay ); |
|
661 } |
|
662 } |
|
663 |
|
664 // ----------------------------------------------------------------------------- |
|
665 // CHgContextUtilityImpl::PublishTimeContextL |
|
666 // ----------------------------------------------------------------------------- |
|
667 // |
|
668 void CHgContextUtilityImpl::PublishTimeContextL( const TTime& aTime, |
|
669 const TTimeIntervalMicroSeconds32& aDelay ) |
|
670 { |
|
671 // YYYYMMDD:HHMMSS.MMMMMM |
|
672 const TInt KDateTimeLength = 22; |
|
673 const TInt KYearLength = 4; |
|
674 const TInt KMonthLength = 2; |
|
675 const TInt KDayLength = 2; |
|
676 _LIT( KTimeZero, ":010101.000000"); |
|
677 |
|
678 TDateTime dt = aTime.DateTime(); |
|
679 TBuf<KDateTimeLength> buf; |
|
680 buf.AppendNumFixedWidth( dt.Year(), EDecimal, KYearLength ); |
|
681 buf.AppendNumFixedWidth( dt.Month(), EDecimal, KMonthLength ); |
|
682 buf.AppendNumFixedWidth( dt.Day(), EDecimal, KDayLength ); |
|
683 buf.Append( KTimeZero ); |
|
684 if ( !aDelay.Int() ) |
|
685 { |
|
686 PublishContextL( KHgCFTypeActiveDate, buf ); |
|
687 } |
|
688 else |
|
689 { |
|
690 PublishContextDelayedL( KHgCFTypeActiveDate, buf, aDelay ); |
|
691 } |
|
692 } |
|
693 |
|
694 // ----------------------------------------------------------------------------- |
|
695 // CHgContextUtilityImpl::PublishPhotoContextL |
|
696 // ----------------------------------------------------------------------------- |
|
697 // |
|
698 void CHgContextUtilityImpl::PublishPhotoContextL( |
|
699 const TDesC& aFilename, |
|
700 const TTimeIntervalMicroSeconds32& aDelay ) |
|
701 { |
|
702 if ( !aDelay.Int() ) |
|
703 { |
|
704 PublishContextL( KHgCFTypePhoto, aFilename ); |
|
705 } |
|
706 else |
|
707 { |
|
708 PublishContextDelayedL( KHgCFTypePhoto, aFilename, aDelay ); |
|
709 } |
|
710 } |
|
711 |
|
712 // ----------------------------------------------------------------------------- |
|
713 // CHgContextUtilityImpl::PublishPhotoContextL |
|
714 // ----------------------------------------------------------------------------- |
|
715 // |
|
716 void CHgContextUtilityImpl::PublishPhotoContextL( |
|
717 TItemId aMdeItemId, |
|
718 CMdESession& aMdeSession, |
|
719 const TTimeIntervalMicroSeconds32& aDelay ) |
|
720 { |
|
721 CMdEObject* obj = aMdeSession.GetObjectL( aMdeItemId ); |
|
722 if ( obj ) |
|
723 { |
|
724 CleanupStack::PushL( obj ); |
|
725 PublishPhotoContextL( obj->Uri(), aDelay ); |
|
726 CleanupStack::PopAndDestroy( obj ); |
|
727 } |
|
728 else |
|
729 { |
|
730 User::Leave( KErrNotFound ); |
|
731 } |
|
732 } |
|
733 |
|
734 // ----------------------------------------------------------------------------- |
|
735 // CHgContextUtilityImpl::PublishTvContextL |
|
736 // ----------------------------------------------------------------------------- |
|
737 // |
|
738 void CHgContextUtilityImpl::PublishTvContextL( const TDesC& aChannelName, |
|
739 const TDesC& aProgramName, const TDesC& aProgramDescription, |
|
740 const TDesC& aGenre ) |
|
741 { |
|
742 TPtrC channelName( aChannelName.Length() ? aChannelName |
|
743 : KHgCFValueUnknownInfo ); |
|
744 TPtrC programName( aProgramName.Length() ? aProgramName |
|
745 : KHgCFValueUnknownInfo ); |
|
746 TPtrC programDesc( aProgramDescription.Length() ? aProgramDescription |
|
747 : KHgCFValueUnknownInfo ); |
|
748 TPtrC programGenre( aGenre.Length() ? aGenre : KHgCFValueUnknownInfo ); |
|
749 |
|
750 // Publish description/genre first because it is unlikely to have those |
|
751 // in rules so their content will be available for sure when an action |
|
752 // is triggered. |
|
753 PublishContextL( KHgCFTypeTvProgramDesc, programDesc ); |
|
754 PublishContextL( KHgCFTypeTvProgramGenre, programGenre ); |
|
755 PublishContextL( KHgCFTypeTvChannelName, channelName ); |
|
756 PublishContextL( KHgCFTypeTvProgramName, programName ); |
|
757 } |
|
758 |
|
759 // ----------------------------------------------------------------------------- |
|
760 // CHgContextUtilityImpl::PublishServiceIdL |
|
761 // ----------------------------------------------------------------------------- |
|
762 // |
|
763 void CHgContextUtilityImpl::PublishServiceIdL( const TDesC& aServiceId, |
|
764 const TDesC& aAccountId, |
|
765 const TTimeIntervalMicroSeconds32& aDelay ) |
|
766 { |
|
767 HBufC* combinedIdBuf = HBufC::NewLC( aServiceId.Length() |
|
768 + aAccountId.Length() + 1 ); |
|
769 TPtr combinedId( combinedIdBuf->Des() ); |
|
770 _LIT( KCombinedFormat, "%S:%S" ); |
|
771 combinedId.Format( KCombinedFormat, &aServiceId, &aAccountId ); |
|
772 PublishContactContextL( combinedId, aDelay ); |
|
773 CleanupStack::PopAndDestroy( combinedIdBuf ); |
|
774 } |
|
775 |
|
776 // ----------------------------------------------------------------------------- |
|
777 // CHgContextUtilityImpl::RePublishWhenFgL |
|
778 // ----------------------------------------------------------------------------- |
|
779 // |
|
780 void CHgContextUtilityImpl::RePublishWhenFgL( TBool aEnable ) |
|
781 { |
|
782 if ( iEnv ) |
|
783 { |
|
784 if ( iFgWatchEnabled ) |
|
785 { |
|
786 iEnv->RemoveForegroundObserver( *this ); |
|
787 } |
|
788 iFgWatchEnabled = aEnable; |
|
789 if ( iFgWatchEnabled ) |
|
790 { |
|
791 iEnv->AddForegroundObserverL( *this ); |
|
792 } |
|
793 } |
|
794 } |
|
795 |
|
796 // callbacks from CCoeEnv |
|
797 |
|
798 // ----------------------------------------------------------------------------- |
|
799 // CHgContextUtilityImpl::HandleGainingForeground |
|
800 // ----------------------------------------------------------------------------- |
|
801 // |
|
802 void CHgContextUtilityImpl::HandleGainingForeground() |
|
803 { |
|
804 if ( iLastContextType && iLastContextData ) |
|
805 { |
|
806 TRAP_IGNORE( PublishContextL( *iLastContextType, *iLastContextData ) ); |
|
807 } |
|
808 } |
|
809 |
|
810 // ----------------------------------------------------------------------------- |
|
811 // CHgContextUtilityImpl::HandleLosingForeground |
|
812 // ----------------------------------------------------------------------------- |
|
813 // |
|
814 void CHgContextUtilityImpl::HandleLosingForeground() |
|
815 { |
|
816 // nothing to do here |
|
817 } |
|
818 |
|
819 // ----------------------------------------------------------------------------- |
|
820 // CHgContextUtilityImpl::IsForeground |
|
821 // ----------------------------------------------------------------------------- |
|
822 // |
|
823 TBool CHgContextUtilityImpl::IsForeground() |
|
824 { |
|
825 if ( iEnv ) |
|
826 { |
|
827 TInt rootWgId = iEnv->RootWin().WindowGroupId(); |
|
828 TInt focusWgId = iEnv->WsSession().GetFocusWindowGroup(); |
|
829 return rootWgId == focusWgId; |
|
830 } |
|
831 else |
|
832 { |
|
833 return ETrue; |
|
834 } |
|
835 } |
|
836 |
|
837 // ----------------------------------------------------------------------------- |
|
838 // CHgContextUtilityImpl::AllowedToPublish |
|
839 // ----------------------------------------------------------------------------- |
|
840 // |
|
841 TBool CHgContextUtilityImpl::AllowedToPublish() |
|
842 { |
|
843 TBool result = !iEnv || iAllowPublishFromBackground || IsForeground(); |
|
844 RDebug::Printf( "[hgctxutil] AllowedToPublish = %d", result ); |
|
845 return result; |
|
846 } |
|
847 |
|
848 // ----------------------------------------------------------------------------- |
|
849 // CHgContextUtilityImpl::AllowPublishFromBackground |
|
850 // ----------------------------------------------------------------------------- |
|
851 // |
|
852 void CHgContextUtilityImpl::AllowPublishFromBackground( TBool aAllow ) |
|
853 { |
|
854 iAllowPublishFromBackground = aAllow; |
|
855 } |
|
856 |
|
857 // ----------------------------------------------------------------------------- |
|
858 // CHgContextUtilityImpl::AddMusicContextInfoL |
|
859 // ----------------------------------------------------------------------------- |
|
860 // |
|
861 void CHgContextUtilityImpl::AddMusicContextInfoL( |
|
862 const TDesC& aKey, const TDesC& aData ) |
|
863 { |
|
864 // Key needs to be provided and also it shouldn't exist in the table. |
|
865 // Latter case is simple safe measure, as RPtrHasMap won't delete existing |
|
866 // objects in InsertL, so adding same key twice would cause memory leak. |
|
867 // The use case of adding same key twice is not 'real world' case, so |
|
868 // this method can simply leave, when same key is offered again. |
|
869 __ASSERT_ALWAYS( aKey.Length(), User::Leave( KErrNotFound ) ); |
|
870 __ASSERT_ALWAYS( |
|
871 !iMusicContextInfo.Find( aKey ), User::Leave( KErrAlreadyExists ) ); |
|
872 |
|
873 // Hash table needs pointers and it should own the pointers, so allocate |
|
874 // key and data, and add them to table. In case the data is empty, add |
|
875 // unknown information, since some data needs to be in the action field. |
|
876 HBufC* key = aKey.AllocLC(); |
|
877 HBufC* data = aData.Length() ? |
|
878 aData.AllocLC() : KHgCFValueUnknownInfo().AllocLC(); |
|
879 iMusicContextInfo.InsertL( key, data ); |
|
880 CleanupStack::Pop( 2, key ); |
|
881 } |
|
882 |
|
883 // ----------------------------------------------------------------------------- |
|
884 // CHgContextUtilityImpl::PublishMusicContextL |
|
885 // ----------------------------------------------------------------------------- |
|
886 // |
|
887 void CHgContextUtilityImpl::PublishMusicContextL( |
|
888 const TTimeIntervalMicroSeconds32& aDelay ) |
|
889 { |
|
890 // If nothing has been done, just leave. No point of publishing entirely |
|
891 // empty music context. |
|
892 __ASSERT_ALWAYS( iMusicContextInfo.Count(), User::Leave( KErrNotReady ) ); |
|
893 |
|
894 // Before publishing anything, make sure all keys contain at least some |
|
895 // data. |
|
896 VerifyAndPublishMusicContextL( KHgCFTypeMusicState, aDelay ); |
|
897 VerifyAndPublishMusicContextL( KHgCFTypeMusicArtist, aDelay ); |
|
898 VerifyAndPublishMusicContextL( KHgCFTypeMusicTitle, aDelay ); |
|
899 VerifyAndPublishMusicContextL( KHgCFTypeMusicAlbum, aDelay ); |
|
900 VerifyAndPublishMusicContextL( KHgCFTypeMusicAlbumArt, aDelay ); |
|
901 VerifyAndPublishMusicContextL( KHgCFTypeMusicUri, aDelay ); |
|
902 VerifyAndPublishMusicContextL( KHgCFTypeMusicGenre, aDelay ); |
|
903 VerifyAndPublishMusicContextL( KHgCFTypeMusicType, aDelay ); |
|
904 |
|
905 // Clear all data from hash table, so new music context can be published. |
|
906 iMusicContextInfo.ResetAndDestroy(); |
|
907 } |
|
908 |
|
909 // ----------------------------------------------------------------------------- |
|
910 // CHgContextUtilityImpl::VerifyAndPublishMusicContextL |
|
911 // ----------------------------------------------------------------------------- |
|
912 // |
|
913 void CHgContextUtilityImpl::VerifyAndPublishMusicContextL( |
|
914 const TDesC& aKey, |
|
915 const TTimeIntervalMicroSeconds32& aDelay ) |
|
916 { |
|
917 TDesC* data = iMusicContextInfo.Find( aKey ); |
|
918 if ( !data ) |
|
919 { |
|
920 // Key didn't contain any data, just create the key with empty info. |
|
921 AddMusicContextInfoL( aKey, KNullDesC ); |
|
922 data = iMusicContextInfo.Find( aKey ); |
|
923 } |
|
924 |
|
925 PublishContextL( aKey, *data, aDelay ); |
|
926 } |
|
927 |
|
928 // ----------------------------------------------------------------------------- |
|
929 // CHgContextUtilityImpl::PublishContextL |
|
930 // ----------------------------------------------------------------------------- |
|
931 // |
|
932 void CHgContextUtilityImpl::PublishContextL( |
|
933 const TDesC & aContextType, |
|
934 const TDesC & aContextData, |
|
935 const TTimeIntervalMicroSeconds32& aDelay ) |
|
936 { |
|
937 if ( !aDelay.Int() ) |
|
938 { |
|
939 PublishContextL( aContextType, aContextData ); |
|
940 } |
|
941 else |
|
942 { |
|
943 PublishContextDelayedL( aContextType, aContextData, aDelay ); |
|
944 } |
|
945 } |
|
946 |
|
947 // ----------------------------------------------------------------------------- |
|
948 // CHgContextUtilityImpl::PublishRadioContextL |
|
949 // ----------------------------------------------------------------------------- |
|
950 // |
|
951 void CHgContextUtilityImpl::PublishRadioContextL( |
|
952 const TDesC& aRadioName, |
|
953 const TDesC& aRadioUrl, |
|
954 const TDesC& aRadioFrequency, |
|
955 const TDesC& aRadioRDSPI ) |
|
956 { |
|
957 TPtrC radioName( aRadioName.Length() ? aRadioName |
|
958 : KHgCFValueUnknownInfo ); |
|
959 TPtrC radioUrl( aRadioUrl.Length() ? aRadioUrl |
|
960 : KHgCFValueUnknownInfo ); |
|
961 TPtrC radioFrequency( aRadioFrequency.Length() ? aRadioFrequency |
|
962 : KHgCFValueUnknownInfo ); |
|
963 TPtrC radioRDSPI( aRadioRDSPI.Length() ? aRadioRDSPI |
|
964 : KHgCFValueUnknownInfo ); |
|
965 |
|
966 PublishContextL( KHgCFTypeMusicRadioRDSPI, radioRDSPI ); |
|
967 PublishContextL( KHgCFTypeMusicRadioFrequency, radioFrequency ); |
|
968 PublishContextL( KHgCFTypeMusicRadioUrl, radioUrl ); |
|
969 PublishContextL( KHgCFTypeMusicRadioName, radioName ); |
|
970 } |
|
971 |
|
972 // end of file |
|