libraries/btrace_parser/src/btrace_context.cpp
changeset 0 7f656887cf89
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // btrace_context.cpp
       
     2 // 
       
     3 // Copyright (c) 2008 - 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "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 // Accenture - Initial contribution
       
    11 //
       
    12 
       
    13 #include <e32debug.h>
       
    14 #include "btrace_parser.h"
       
    15 
       
    16 
       
    17 _LIT(KUnknown, "unknown");
       
    18 
       
    19 
       
    20 EXPORT_C TBtraceIdBase::TBtraceIdBase()
       
    21 	: iId(0)
       
    22 	{
       
    23 	}
       
    24 
       
    25 EXPORT_C TBtraceIdBase::TBtraceIdBase(TUint aId)
       
    26 	: iId(aId)
       
    27 	{
       
    28 	}
       
    29 
       
    30 EXPORT_C TBtraceIdBase::TBtraceIdBase(const TBtraceIdBase& aId)
       
    31 	: iId(aId.Value())
       
    32 	{
       
    33 	}
       
    34 
       
    35 EXPORT_C void TBtraceIdBase::Set(TUint aValue)
       
    36 	{
       
    37 	iId = aValue;
       
    38 	}
       
    39 
       
    40 EXPORT_C TUint TBtraceIdBase::Value() const
       
    41 	{
       
    42 	return iId;
       
    43 	}
       
    44 
       
    45 EXPORT_C TBool TBtraceIdBase::operator==(const TBtraceIdBase& aId) const
       
    46 	{
       
    47 	return (aId.iId == iId);
       
    48 	}
       
    49 
       
    50 EXPORT_C TBtraceThreadId::TBtraceThreadId()
       
    51 	{
       
    52 	}
       
    53 
       
    54 EXPORT_C TBtraceThreadId::TBtraceThreadId(TUint aId)
       
    55 	: TBtraceIdBase(aId)
       
    56 	{
       
    57 	}
       
    58 
       
    59 EXPORT_C TBtraceThreadId::TBtraceThreadId(const TBtraceThreadId& aId)
       
    60 	: TBtraceIdBase(aId)
       
    61 	{
       
    62 	}
       
    63 
       
    64 EXPORT_C TBtraceProcessId::TBtraceProcessId()
       
    65 	{
       
    66 	}
       
    67 
       
    68 EXPORT_C TBtraceProcessId::TBtraceProcessId(TUint aId)
       
    69 	: TBtraceIdBase(aId)
       
    70 	{
       
    71 	}
       
    72 
       
    73 EXPORT_C TBtraceProcessId::TBtraceProcessId(const TBtraceProcessId& aId)
       
    74 	: TBtraceIdBase(aId)
       
    75 	{
       
    76 	}
       
    77 
       
    78 EXPORT_C TBtraceWindowGroupId::TBtraceWindowGroupId()
       
    79 	{
       
    80 	}
       
    81 
       
    82 EXPORT_C TBtraceWindowGroupId::TBtraceWindowGroupId(TUint aId)
       
    83 	: TBtraceIdBase(aId)
       
    84 	{
       
    85 	}
       
    86 
       
    87 EXPORT_C TBtraceWindowGroupId::TBtraceWindowGroupId(const TBtraceWindowGroupId& aId)
       
    88 	: TBtraceIdBase(aId)
       
    89 	{
       
    90 	}
       
    91 
       
    92 EXPORT_C void MBtraceContextObserver::HandleThreadSeenL(const TBtraceTickCount&, const TBtraceThreadId&, TUint)
       
    93 	{
       
    94 	Panic(EBtpPanicUndefinedCallBack);
       
    95 	}
       
    96 
       
    97 EXPORT_C void MBtraceContextObserver::HandleThreadGoneL(const TBtraceTickCount&, const TBtraceThreadId&, TUint)
       
    98 	{
       
    99 	Panic(EBtpPanicUndefinedCallBack);
       
   100 	}
       
   101 
       
   102 EXPORT_C void MBtraceContextObserver::HandleThreadExitL(const TBtraceTickCount&, const TBtraceThreadId&, TExitType, TInt, const TDesC&, TUint)
       
   103 	{
       
   104 	Panic(EBtpPanicUndefinedCallBack);
       
   105 	}
       
   106 
       
   107 EXPORT_C void MBtraceContextObserver::HandleWindowGroupSeenL(const TBtraceTickCount&, const TBtraceWindowGroupId&, TUint)
       
   108 	{
       
   109 	Panic(EBtpPanicUndefinedCallBack);
       
   110 	}
       
   111 
       
   112 EXPORT_C CBtraceContext* CBtraceContext::NewL(CBtraceReader& aReader, TMode aMode)
       
   113 	{
       
   114 	CBtraceContext* self = new(ELeave) CBtraceContext(aReader, aMode);
       
   115 	CleanupStack::PushL(self);
       
   116 	self->ConstructL();
       
   117 	CleanupStack::Pop(self);
       
   118 	return self;
       
   119 	}
       
   120 
       
   121 EXPORT_C CBtraceContext::~CBtraceContext()
       
   122 	{
       
   123 	iWindowGroupSeenNotifs.Close();
       
   124 	iThreadExitNotifs.Close();
       
   125 	iThreadGoneNotifs.Close();
       
   126 	iThreadSeenNotifs.Close();
       
   127 	iWindowGroups.Close();
       
   128 	iThreads.Close();
       
   129 	iProcesses.Close();
       
   130 	iReader.RemoveObserver(BTrace::EThreadIdentification, *this);
       
   131 	iReader.RemoveObserver(KAmTraceCategory, *this);
       
   132 	}
       
   133 
       
   134 
       
   135 TBool CBtraceContext::ThreadMatchesId(const TThread& aLeft, const TThread& aRight)
       
   136 	{
       
   137 	return (aLeft.iId == aRight.iId);
       
   138 	}
       
   139 
       
   140 TBool CBtraceContext::ThreadMatchesKernelId(const TThread& aLeft, const TThread& aRight)
       
   141 	{
       
   142 	return (aLeft.iKernelId == aRight.iKernelId);
       
   143 	}
       
   144 
       
   145 TBool CBtraceContext::ThreadMatchesNThreadAddress(const TThread& aLeft, const TThread& aRight)
       
   146 	{
       
   147 	return (aLeft.iNThreadAddress == aRight.iNThreadAddress);
       
   148 	}
       
   149 
       
   150 TBool CBtraceContext::ProcessMatchesId(const TProcess& aLeft, const TProcess& aRight)
       
   151 	{
       
   152 	return (aLeft.iId == aRight.iId);
       
   153 	}
       
   154 
       
   155 TBool CBtraceContext::ProcessMatchesDProcessAddress(const TProcess& aLeft, const TProcess& aRight)
       
   156 	{
       
   157 	return (aLeft.iDProcessAddress == aRight.iDProcessAddress);
       
   158 	}
       
   159 
       
   160 TBool CBtraceContext::WindowGroupMatchesId(const TWindowGroup& aLeft, const TWindowGroup& aRight)
       
   161 	{
       
   162 	return (aLeft.iId == aRight.iId);
       
   163 	}
       
   164 
       
   165 TBool CBtraceContext::WindowGroupMatchesThreadId(const TWindowGroup& aLeft, const TWindowGroup& aRight)
       
   166 	{
       
   167 	return (aLeft.iThreadId == aRight.iThreadId);
       
   168 	}
       
   169 
       
   170 TBool CBtraceContext::WindowGroupMatchesWServId(const TWindowGroup& aLeft, const TWindowGroup& aRight)
       
   171 	{
       
   172 	return (aLeft.iWindowGroupId == aRight.iWindowGroupId);
       
   173 	}
       
   174 
       
   175 EXPORT_C const TDesC& CBtraceContext::ThreadName(const TBtraceThreadId& aId) const
       
   176 	{
       
   177 	TThread findKey(0, 0, KNullDesC8);
       
   178 	findKey.iId = aId;
       
   179 	TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesId));
       
   180 	if (pos >= 0)
       
   181 		{
       
   182 		return iThreads[pos].iName;
       
   183 		}
       
   184 	else
       
   185 		{
       
   186 		return KUnknown;
       
   187 		}
       
   188 	}
       
   189 
       
   190 EXPORT_C void CBtraceContext::GetFullThreadName(const TBtraceThreadId& aId, TDes& aFullName) const
       
   191 	{
       
   192 	TThread findKey(0, 0, KNullDesC8);
       
   193 	findKey.iId = aId;
       
   194 	TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesId));
       
   195 	if (pos >= 0)
       
   196 		{
       
   197 		const TThread& thread = iThreads[pos];
       
   198 		TProcess findKey(thread.iOwningProcess);
       
   199 		TInt processPos = iProcesses.Find(findKey, TIdentityRelation<TProcess>(ProcessMatchesDProcessAddress));
       
   200 		__ASSERT_ALWAYS(processPos >= 0, Panic(EBtpPanicFailedToFindProcess));
       
   201 		aFullName.Zero();
       
   202 		aFullName.Append(ProcessName(iProcesses[processPos].iId));
       
   203 		aFullName.Append(_L("::"));
       
   204 		aFullName.Append(thread.iName);
       
   205 		}
       
   206 	else
       
   207 		{
       
   208 		aFullName = KUnknown;
       
   209 		}
       
   210 	}
       
   211 
       
   212 EXPORT_C TThreadId CBtraceContext::ThreadId(const TBtraceThreadId& aId) const
       
   213 	{
       
   214 	TThread findKey(0, 0, KNullDesC8);
       
   215 	findKey.iId = aId;
       
   216 	TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesId));
       
   217 	__ASSERT_ALWAYS(pos >= 0, Panic(EBtpPanicThreadIdNotFound));
       
   218 	return iThreads[pos].iKernelId;
       
   219 	}
       
   220 
       
   221 EXPORT_C const TDesC& CBtraceContext::ProcessName(const TBtraceProcessId& aId) const
       
   222 	{
       
   223 	TProcess findKey(0);
       
   224 	findKey.iId = aId;
       
   225 	TInt pos = iProcesses.Find(findKey, TIdentityRelation<TProcess>(ProcessMatchesId));
       
   226 	__ASSERT_ALWAYS(pos >= 0, Panic(EBtpPanicProcessNameNotFound));
       
   227 	return iProcesses[pos].iName;
       
   228 	}
       
   229 
       
   230 EXPORT_C TInt CBtraceContext::WindowGroupId(const TBtraceWindowGroupId& aId) const
       
   231 	{
       
   232 	TWindowGroup findKey(0, 0, KNullDesC);
       
   233 	findKey.iId = aId;
       
   234 	TInt pos = iWindowGroups.Find(findKey, TIdentityRelation<TWindowGroup>(WindowGroupMatchesId));
       
   235 	__ASSERT_ALWAYS(pos >= 0, Panic(EBtpPanicWindowGroupIdNotFound));
       
   236 	return iWindowGroups[pos].iWindowGroupId;
       
   237 	}
       
   238 
       
   239 EXPORT_C const TDesC& CBtraceContext::WindowGroupName(const TBtraceWindowGroupId& aId) const
       
   240 	{
       
   241 	TWindowGroup findKey(0, 0, KNullDesC);
       
   242 	findKey.iId = aId;
       
   243 	TInt pos = iWindowGroups.Find(findKey, TIdentityRelation<TWindowGroup>(WindowGroupMatchesId));
       
   244 	__ASSERT_ALWAYS(pos >= 0, Panic(EBtpPanicWindowGroupIdNotFound));
       
   245 	return iWindowGroups[pos].iName;
       
   246 	}
       
   247 
       
   248 EXPORT_C const TBtraceThreadId* CBtraceContext::FindThread(TUint32 aNThreadAddress) const
       
   249 	{
       
   250 	TThread findKey(aNThreadAddress, 0, KNullDesC8);
       
   251 	TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesNThreadAddress));
       
   252 	if (pos >= 0)
       
   253 		{
       
   254 		return &iThreads[pos].iId;
       
   255 		}
       
   256 	else
       
   257 		{
       
   258 		return NULL;
       
   259 		}
       
   260 	}
       
   261 
       
   262 EXPORT_C const TBtraceThreadId* CBtraceContext::FindThread(const TThreadId& aId) const
       
   263 	{
       
   264 	TThread findKey(0, 0, KNullDesC8);
       
   265 	findKey.iKernelId = TUint(aId);
       
   266 	TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesKernelId));
       
   267 	if (pos >= 0)
       
   268 		{
       
   269 		return &iThreads[pos].iId;
       
   270 		}
       
   271 	else
       
   272 		{
       
   273 		return NULL;
       
   274 		}
       
   275 	}
       
   276 
       
   277 EXPORT_C const TBtraceWindowGroupId* CBtraceContext::FindWindowGroup(TInt aWServWgId) const
       
   278 	{
       
   279 	TWindowGroup findKey(aWServWgId);
       
   280 	TInt pos = iWindowGroups.Find(findKey, TIdentityRelation<TWindowGroup>(WindowGroupMatchesWServId));
       
   281 	if (pos >= 0)
       
   282 		{
       
   283 		return &iWindowGroups[pos].iId;
       
   284 		}
       
   285 	else
       
   286 		{
       
   287 		return NULL;
       
   288 		}
       
   289 	}
       
   290 
       
   291 EXPORT_C void CBtraceContext::FindThreadsL(const TDesC& aPattern, RArray<TBtraceThreadId>& aThreads) const
       
   292 	{
       
   293 	TInt count = iThreads.Count();
       
   294 	while (--count >= 0)
       
   295 		{
       
   296 		const TThread& thread = iThreads[count];
       
   297 		TFullName name;
       
   298 		GetFullThreadName(thread.iId, name);
       
   299 		if (name.MatchF(aPattern) != KErrNotFound)
       
   300 			{
       
   301 			aThreads.AppendL(thread.iId);
       
   302 			}
       
   303 		}
       
   304 	}
       
   305 
       
   306 EXPORT_C void CBtraceContext::FindWindowGroupsL(const TDesC& aPattern, RArray<TBtraceWindowGroupId>& aWindowGroups) const
       
   307 	{
       
   308 	TInt count = iWindowGroups.Count();
       
   309 	while (--count >= 0)
       
   310 		{
       
   311 		const TWindowGroup& windowGroup = iWindowGroups[count];
       
   312 		if (windowGroup.iName.MatchF(aPattern) != KErrNotFound)
       
   313 			{
       
   314 			aWindowGroups.AppendL(windowGroup.iId);
       
   315 			}
       
   316 		}
       
   317 	}
       
   318 
       
   319 EXPORT_C void CBtraceContext::FindWindowGroupsByThreadName(const TDesC& aPattern, RArray<TBtraceWindowGroupId>& aWindowGroups) const
       
   320 	{
       
   321 	TInt count = iThreads.Count();
       
   322 	while (--count >= 0)
       
   323 		{
       
   324 		const TThread& thread = iThreads[count];
       
   325 		TFullName name;
       
   326 		GetFullThreadName(thread.iId, name);
       
   327 		if (name.MatchF(aPattern) != KErrNotFound)
       
   328 			{
       
   329 			for (TInt i = (iWindowGroups.Count() - 1); i >= 0; --i)
       
   330 				{
       
   331 				const TWindowGroup& thisWindowGroup = iWindowGroups[i];
       
   332 				if (thisWindowGroup.iThreadId.Id() == thread.iKernelId)
       
   333 					{
       
   334 					aWindowGroups.AppendL(thisWindowGroup.iId);
       
   335 					}
       
   336 				}
       
   337 			}
       
   338 		}
       
   339 	}
       
   340 
       
   341 EXPORT_C void CBtraceContext::NotifyThreadSeenL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId)
       
   342 	{
       
   343 	NotifyThreadSeenL(aPattern, aObserver, aId, ENotificationOneShot);
       
   344 	}
       
   345 
       
   346 EXPORT_C void CBtraceContext::NotifyThreadSeenL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId, TBtraceNotificationPersistence aPersistence)
       
   347 	{
       
   348 	iThreadSeenNotifs.AppendL(TThreadSeenNotif(aId, aPattern, aObserver, aPersistence));
       
   349 	}
       
   350 
       
   351 EXPORT_C void CBtraceContext::CancelNotifyThreadSeen(MBtraceContextObserver& aObserver)
       
   352 	{
       
   353 	for (TInt i = (iThreadSeenNotifs.Count() - 1); i >= 0; --i)
       
   354 		{
       
   355 		if (&iThreadSeenNotifs[i].iObserver == &aObserver)
       
   356 			{
       
   357 			iThreadSeenNotifs.Remove(i);
       
   358 			}
       
   359 		}
       
   360 	}
       
   361 
       
   362 EXPORT_C void CBtraceContext::NotifyThreadGoneL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId)
       
   363 	{
       
   364 	return NotifyThreadGoneL(aPattern, aObserver, aId, ENotificationOneShot);
       
   365 	}
       
   366 	
       
   367 EXPORT_C void CBtraceContext::NotifyThreadGoneL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId, TBtraceNotificationPersistence aPersistence)
       
   368 	{
       
   369 	iThreadGoneNotifs.AppendL(TThreadGoneNotif(aId, aPattern, aObserver, aPersistence));
       
   370 	}
       
   371 
       
   372 EXPORT_C void CBtraceContext::CancelNotifyThreadGone(MBtraceContextObserver& aObserver)
       
   373 	{
       
   374 	for (TInt i = (iThreadGoneNotifs.Count() - 1); i >= 0; --i)
       
   375 		{
       
   376 		if (&iThreadGoneNotifs[i].iObserver == &aObserver)
       
   377 			{
       
   378 			iThreadGoneNotifs.Remove(i);
       
   379 			}
       
   380 		}
       
   381 	}
       
   382 
       
   383 EXPORT_C void CBtraceContext::NotifyThreadExitL(const TDesC& aPattern, TUint aExitTypes, TInt* aReason, const TDesC* aCategory, MBtraceContextObserver& aObserver, TUint aId, TBtraceNotificationPersistence aPersistence)
       
   384 	{
       
   385 	iThreadExitNotifs.AppendL(TThreadExitNotif(aId, aPattern, aExitTypes, aReason, aCategory, aObserver, aPersistence));
       
   386 	}
       
   387 
       
   388 EXPORT_C void CBtraceContext::CancelNotifyThreadExit(MBtraceContextObserver& aObserver)
       
   389 	{
       
   390 	for (TInt i = (iThreadExitNotifs.Count() - 1); i >= 0; --i)
       
   391 		{
       
   392 		if (&iThreadExitNotifs[i].iObserver == &aObserver)
       
   393 			{
       
   394 			iThreadExitNotifs.Remove(i);
       
   395 			}
       
   396 		}
       
   397 	}
       
   398 
       
   399 EXPORT_C void CBtraceContext::NotifyWindowGroupSeenL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId, TBtraceNotificationPersistence aPersistence)
       
   400 	{
       
   401 	iWindowGroupSeenNotifs.AppendL(TWindowGroupSeenNotif(aId, aPattern, TWindowGroupSeenNotif::EWindowGroupName, aObserver, aPersistence));
       
   402 	}
       
   403 
       
   404 EXPORT_C void CBtraceContext::NotifyWindowGroupSeenByThreadNameL(const TDesC& aPattern, MBtraceContextObserver& aObserver, TUint aId, TBtraceNotificationPersistence aPersistence)
       
   405 	{
       
   406 	iWindowGroupSeenNotifs.AppendL(TWindowGroupSeenNotif(aId, aPattern, TWindowGroupSeenNotif::EThreadName, aObserver, aPersistence));
       
   407 	}
       
   408 
       
   409 EXPORT_C void CBtraceContext::CancelNotifyWindowGroupSeen(MBtraceContextObserver& aObserver)
       
   410 	{
       
   411 	for (TInt i = (iWindowGroupSeenNotifs.Count() - 1); i >= 0; --i)
       
   412 		{
       
   413 		if (&iWindowGroupSeenNotifs[i].iObserver == &aObserver)
       
   414 			{
       
   415 			iWindowGroupSeenNotifs.Remove(i);
       
   416 			}
       
   417 		}
       
   418 	}
       
   419 
       
   420 CBtraceContext::CBtraceContext(CBtraceReader& aReader, TMode aMode)
       
   421 	: iMode(aMode), iReader(aReader), iNextBtraceThreadId(KMaxTUint), iNextBtraceProcessId(KMaxTUint)
       
   422 	{
       
   423 	}
       
   424 
       
   425 void CBtraceContext::ConstructL()
       
   426 	{
       
   427 	iReader.AddObserverL(BTrace::EThreadIdentification, *this, CBtraceReader::EIncludeSynchronizationFrames);
       
   428 	iReader.AddObserverL(KAmTraceCategory, *this);
       
   429 	}
       
   430 
       
   431 TUint CBtraceContext::GetNextThreadId()
       
   432 	{
       
   433 	TUint id = iNextBtraceThreadId--;
       
   434 	__ASSERT_ALWAYS(iNextBtraceThreadId > 0, Panic(EBtpPanicBtraceThreadIdOverflow));
       
   435 	return id;
       
   436 	}
       
   437 
       
   438 TUint CBtraceContext::GetNextProcessId()
       
   439 	{
       
   440 	TUint id = iNextBtraceProcessId--;
       
   441 	__ASSERT_ALWAYS(iNextBtraceProcessId > 0, Panic(EBtpPanicBtraceProcessIdOverflow));
       
   442 	return id;
       
   443 	}
       
   444 
       
   445 TUint CBtraceContext::GetNextWindowGroupId()
       
   446 	{
       
   447 	TUint id = iNextBtraceWindowGroupId--;
       
   448 	__ASSERT_ALWAYS(iNextBtraceWindowGroupId > 0, Panic(EBtpPanicBtraceWindowGroupIdOverflow));
       
   449 	return id;
       
   450 	}
       
   451 
       
   452 void CBtraceContext::SeenL(const TThread& aThread, const TBtraceTickCount& aTickCount)
       
   453 	{
       
   454 	TFullName name;
       
   455 	GetFullThreadName(aThread.iId, name);
       
   456 	for (TInt i = (iThreadSeenNotifs.Count() - 1); i >= 0; --i)
       
   457 		{
       
   458 		const TThreadSeenNotif& thisNotif = iThreadSeenNotifs[i];
       
   459 		if (name.MatchF(thisNotif.iPattern) != KErrNotFound)
       
   460 			{
       
   461 			MBtraceContextObserver& observer = thisNotif.iObserver;
       
   462 			TUint id = thisNotif.iId;
       
   463 			if (thisNotif.iPersistence == ENotificationOneShot)
       
   464 				{
       
   465 				iThreadSeenNotifs.Remove(i);
       
   466 				}
       
   467 			observer.HandleThreadSeenL(aTickCount, aThread.iId, id);
       
   468 			}
       
   469 		}
       
   470 	}
       
   471 
       
   472 void CBtraceContext::GoneL(const TThread& aThread, const TBtraceTickCount& aTickCount)
       
   473 	{
       
   474 	TFullName name;
       
   475 	GetFullThreadName(aThread.iId, name);
       
   476 	for (TInt i = (iThreadGoneNotifs.Count() - 1); i >= 0; --i)
       
   477 		{
       
   478 		const TThreadGoneNotif& notif = iThreadGoneNotifs[i];
       
   479 		if (name.MatchF(notif.iPattern) != KErrNotFound)
       
   480 			{
       
   481 			MBtraceContextObserver& observer = notif.iObserver;
       
   482 			TUint id = notif.iId;
       
   483 			if (notif.iPersistence == ENotificationOneShot)
       
   484 				{
       
   485 				iThreadGoneNotifs.Remove(i);
       
   486 				}
       
   487 			observer.HandleThreadGoneL(aTickCount, aThread.iId, id);
       
   488 			}
       
   489 		}
       
   490 	}
       
   491 
       
   492 void CBtraceContext::ExitedL(const TThread& aThread, TExitType aExitType, TInt aReason, const TDesC& aCategory, const TBtraceTickCount& aTickCount)
       
   493 	{
       
   494 	TFullName name;
       
   495 	GetFullThreadName(aThread.iId, name);
       
   496 	for (TInt i = (iThreadExitNotifs.Count() - 1); i >= 0; --i)
       
   497 		{
       
   498 		const TThreadExitNotif& notif = iThreadExitNotifs[i];
       
   499 		if (notif.Matches(name, aExitType, aReason, aCategory))
       
   500 			{
       
   501 			MBtraceContextObserver& observer = notif.iObserver;
       
   502 			TUint id = notif.iId;
       
   503 			if (notif.iPersistence == ENotificationOneShot)
       
   504 				{
       
   505 				iThreadExitNotifs.Remove(i);
       
   506 				}
       
   507 			observer.HandleThreadExitL(aTickCount, aThread.iId, aExitType, aReason, aCategory, id);
       
   508 			}
       
   509 		}
       
   510 	}
       
   511 
       
   512 void CBtraceContext::SeenL(const TWindowGroup& aWindowGroup, const TBtraceTickCount& aTickCount)
       
   513 	{
       
   514 	for (TInt i = (iWindowGroupSeenNotifs.Count() - 1); i >= 0; --i)
       
   515 		{
       
   516 		const TWindowGroupSeenNotif& thisNotif = iWindowGroupSeenNotifs[i];
       
   517 		if (thisNotif.iPatternType == TWindowGroupSeenNotif::EWindowGroupName)
       
   518 			{
       
   519 			if (aWindowGroup.iName.MatchF(thisNotif.iPattern) != KErrNotFound)
       
   520 				{
       
   521 				MBtraceContextObserver& observer = thisNotif.iObserver;
       
   522 				TUint id = thisNotif.iId;
       
   523 				if (thisNotif.iPersistence == ENotificationOneShot)
       
   524 					{
       
   525 					iWindowGroupSeenNotifs.Remove(i);
       
   526 					}
       
   527 				observer.HandleWindowGroupSeenL(aTickCount, aWindowGroup.iId, id);
       
   528 				}
       
   529 			}
       
   530 		else
       
   531 			{
       
   532 			TThread findKey(0, 0, KNullDesC8);
       
   533 			findKey.iKernelId = TUint(aWindowGroup.iThreadId);
       
   534 			TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesKernelId));
       
   535 			if (pos >= 0)
       
   536 				{
       
   537 				TFullName threadName;
       
   538 				GetFullThreadName(iThreads[pos].iId, threadName);
       
   539 				if (threadName.MatchF(thisNotif.iPattern))
       
   540 					{
       
   541 					MBtraceContextObserver& observer = thisNotif.iObserver;
       
   542 					TUint id = thisNotif.iId;
       
   543 					if (thisNotif.iPersistence == ENotificationOneShot)
       
   544 						{
       
   545 						iWindowGroupSeenNotifs.Remove(i);
       
   546 						}
       
   547 					observer.HandleWindowGroupSeenL(aTickCount, aWindowGroup.iId, id);
       
   548 					}
       
   549 				}
       
   550 			}
       
   551 		}
       
   552 	}
       
   553 
       
   554 void CBtraceContext::HandleBtraceFrameL(const TBtraceFrame& aFrame)
       
   555 	{
       
   556 	const TUint8* data = aFrame.iData.Ptr();
       
   557 
       
   558 	if (aFrame.iCategory == BTrace::EThreadIdentification)
       
   559 		{
       
   560 		switch (aFrame.iSubCategory)
       
   561 			{
       
   562 			case BTrace::EThreadCreate:
       
   563 				{
       
   564 				TUint32 nthreadAddress = *(TUint32*)data;
       
   565 				TUint32 dprocessAddress = *((TUint32*)data + 1);
       
   566 				TPtrC8 name(aFrame.iData.Mid(8));
       
   567 
       
   568 #ifdef BTRACE_CONTEXT_DEBUG
       
   569 				TFullName name16;
       
   570 				name16.Copy(name);
       
   571 				RDebug::Print(_L("BTrace::EThreadCreate: 0x%08x \"%S\""), nthreadAddress, &name16);
       
   572 #endif
       
   573 
       
   574 				TThread thread(nthreadAddress, dprocessAddress, name);
       
   575 				AppendL(thread, aFrame.iTickCount);
       
   576 				break;
       
   577 				}
       
   578 			case BTrace::EThreadDestroy:
       
   579 				{
       
   580 				TUint32 nthreadAddress = *(TUint32*)data;
       
   581 				TThread findKey(nthreadAddress, 0, KNullDesC8);
       
   582 				TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesNThreadAddress));
       
   583 				if (pos >= 0)
       
   584 					{
       
   585 #ifdef BTRACE_CONTEXT_DEBUG
       
   586 					RDebug::Print(_L("BTrace::EThreadDestroy: %u %u 0x%08x \"%S\""), iThreads[pos].iId.Value(), iThreads[pos].iKernelId, nthreadAddress, &iThreads[pos].iName);
       
   587 #endif
       
   588 					GoneL(iThreads[pos], aFrame.iTickCount);
       
   589 					RemoveThread(pos);
       
   590 					}
       
   591 				else
       
   592 					{
       
   593 					// This can happen if a thread is destroyed after the btrace buffer has been enabled but before the BTrace::EThreadIdentification category has been enabled.
       
   594 					iReader.Log(_L("Destroyed thread 0x%08x not found\r\n"), nthreadAddress);
       
   595 					}
       
   596 				break;
       
   597 				}
       
   598 			case BTrace::EThreadName:
       
   599 				{
       
   600 				TUint32 nthreadAddress = *(TUint32*)data;
       
   601 				TUint32 dprocessAddress = *((TUint32*)data + 1);
       
   602 				TPtrC8 name(aFrame.iData.Mid(8));
       
   603 
       
   604 #ifdef BTRACE_CONTEXT_DEBUG
       
   605 				TFullName name16;
       
   606 				name16.Copy(name);
       
   607 				RDebug::Print(_L("BTrace::EThreadName: 0x%08x \"%S\""), nthreadAddress, &name16);
       
   608 #endif				
       
   609 				TThread findKey(nthreadAddress, 0, KNullDesC8);
       
   610 				TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesNThreadAddress));
       
   611 				if (pos >= 0)
       
   612 					{
       
   613 					iThreads[pos].iName.Copy(name);
       
   614 					SeenL(iThreads[pos], aFrame.iTickCount);
       
   615 					}
       
   616 				else
       
   617 					{
       
   618 					TThread thread(nthreadAddress, dprocessAddress, name);
       
   619 					AppendL(thread, aFrame.iTickCount);
       
   620 					}
       
   621 				break;
       
   622 				}
       
   623 			case BTrace::EProcessCreate:
       
   624 				{
       
   625 				TUint32 dprocessAddress = *(TUint32*)data;
       
   626 #ifdef BTRACE_CONTEXT_DEBUG
       
   627 				RDebug::Print(_L("BTrace::EProcessCreate: 0x%08x"), dprocessAddress);
       
   628 #endif
       
   629 				TProcess process(dprocessAddress);
       
   630 				AppendL(process, aFrame.iTickCount);
       
   631 				break;
       
   632 				}
       
   633 			case BTrace::EProcessName:
       
   634 				{
       
   635 				TUint32 dprocessAddress = *((TUint32*)data + 1);
       
   636 				TPtrC8 name(aFrame.iData.Mid(8));
       
   637 
       
   638 #ifdef BTRACE_CONTEXT_DEBUG
       
   639 				TFullName name16;
       
   640 				name16.Copy(name);
       
   641 				RDebug::Print(_L("BTrace::EProcessName: 0x%08x \"%S\""), dprocessAddress, &name16);
       
   642 #endif
       
   643 				TProcess findKey(dprocessAddress);
       
   644 				TInt pos = iProcesses.Find(findKey, TIdentityRelation<TProcess>(ProcessMatchesDProcessAddress));
       
   645 				if (pos >= 0)
       
   646 					{
       
   647 					iProcesses[pos].iName.Copy(name);
       
   648 					SeenAllThreadsL(iProcesses[pos], aFrame.iTickCount);
       
   649 					}
       
   650 				else
       
   651 					{
       
   652 					TProcess process(dprocessAddress, name);
       
   653 					AppendL(process, aFrame.iTickCount);
       
   654 					}
       
   655 				break;
       
   656 				}
       
   657 			case BTrace::EThreadId:
       
   658 				{
       
   659 				TUint32 nthreadAddress = *(TUint32*)data;
       
   660 				TUint32 threadId = *((TUint32*)data + 2);
       
   661 				TThread findKey(nthreadAddress, 0, KNullDesC8);
       
   662 				TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesNThreadAddress));
       
   663 				__ASSERT_ALWAYS(pos >= 0, Panic(EBtpPanicThreadNotFoundForId));
       
   664 				iThreads[pos].iKernelId = threadId;
       
   665 #ifdef BTRACE_CONTEXT_DEBUG
       
   666 				RDebug::Print(_L("BTrace::EThreadId: %u 0x%08x \"%S\""), threadId, nthreadAddress, &iThreads[pos].iName);
       
   667 #endif
       
   668 				break;
       
   669 				}
       
   670 			default:
       
   671 				{
       
   672 				// Ignore anything we don't know about.
       
   673 				break;
       
   674 				}
       
   675 			}
       
   676 		}
       
   677 	else if (aFrame.iCategory == KAmTraceCategory)
       
   678 		{
       
   679 		if (aFrame.iSubCategory == EAmTraceSubCategoryWindowGroupName)
       
   680 			{
       
   681 			TUint wgId = *(TUint32*)data;
       
   682 			TInt kernelThreadId = *((TInt32*)data + 1);
       
   683 			TPtrC8 nameData = aFrame.iData.Mid(8);
       
   684 			TPtrC name((TUint16*)nameData.Ptr(), nameData.Length() / 2);
       
   685 			TWindowGroup findKey(wgId);
       
   686 			TInt pos = iWindowGroups.Find(findKey, TIdentityRelation<TWindowGroup>(WindowGroupMatchesWServId));
       
   687 			if (pos >= 0)
       
   688 				{
       
   689 				TWindowGroup& windowGroup = iWindowGroups[pos];
       
   690 				windowGroup.iName = name;
       
   691 				SeenL(windowGroup, aFrame.iTickCount);
       
   692 				}
       
   693 			else
       
   694 				{
       
   695 				TWindowGroup windowGroup(wgId, TThreadId(kernelThreadId), name);
       
   696 				windowGroup.iId.Set(GetNextWindowGroupId());
       
   697 				iWindowGroups.AppendL(windowGroup);
       
   698 				SeenL(windowGroup, aFrame.iTickCount);
       
   699 				}
       
   700 			}
       
   701 		else if ((aFrame.iSubCategory >= EAmTraceSubCategoryThreadKilled) && (aFrame.iSubCategory <= EAmTraceSubCategoryThreadPanicked))
       
   702 			{
       
   703 			TUint id = *(TUint32*)data;
       
   704 			TInt reason = *((TInt32*)data + 1);
       
   705 			TThread findKey(0, 0, KNullDesC8);
       
   706 			findKey.iKernelId = id;
       
   707 			TInt pos = iThreads.Find(findKey, TIdentityRelation<TThread>(ThreadMatchesKernelId));
       
   708 			if (pos >= 0)
       
   709 				{
       
   710 				const TThread& thread = iThreads[pos];
       
   711 				switch (aFrame.iSubCategory)
       
   712 					{
       
   713 					case EAmTraceSubCategoryThreadKilled:
       
   714 						{
       
   715 						ExitedL(thread, EExitKill, reason, KNullDesC, aFrame.iTickCount);
       
   716 						break;
       
   717 						}
       
   718 					case EAmTraceSubCategoryThreadTerminated:
       
   719 						{
       
   720 						ExitedL(thread, EExitTerminate, reason, KNullDesC, aFrame.iTickCount);
       
   721 						break;
       
   722 						}
       
   723 					case EAmTraceSubCategoryThreadPanicked:
       
   724 						{
       
   725 						TPtrC8 narrowCategory(aFrame.iData.Mid(sizeof(TInt) * 2));
       
   726 						TExitCategoryName category;
       
   727 						category.Copy(narrowCategory);
       
   728 						ExitedL(thread, EExitPanic, reason, category, aFrame.iTickCount);
       
   729 						break;
       
   730 						}
       
   731 					default:
       
   732 						{
       
   733 						// Ignore anything we don't know about.
       
   734 						break;
       
   735 						}
       
   736 					}
       
   737 				}
       
   738 			}
       
   739 		}
       
   740 	}
       
   741 
       
   742 void CBtraceContext::AppendL(const TThread& aThread, const TBtraceTickCount& aTickCount)
       
   743 	{
       
   744 	iThreads.AppendL(aThread);
       
   745 	TThread& thread = iThreads[iThreads.Count() - 1];
       
   746 	thread.iId.Set(GetNextThreadId());
       
   747 
       
   748 	// Increment the reference count of the owning process.
       
   749 	TProcess findKey(thread.iOwningProcess);
       
   750 	TInt pos = iProcesses.Find(findKey, TIdentityRelation<TProcess>(ProcessMatchesDProcessAddress));
       
   751 	if (pos >= 0)
       
   752 		{
       
   753 		++(iProcesses[pos].iReferenceCount);
       
   754 		}
       
   755 
       
   756 	SeenL(thread, aTickCount);
       
   757 	}
       
   758 
       
   759 void CBtraceContext::AppendL(const TProcess& aProcess, const TBtraceTickCount& aTickCount)
       
   760 	{
       
   761 	iProcesses.AppendL(aProcess);
       
   762 	TProcess& process = iProcesses[iProcesses.Count() - 1];
       
   763 	process.iId.Set(GetNextProcessId());
       
   764 
       
   765 	// Set the reference count for this process.
       
   766 	for (TInt i = (iThreads.Count() - 1); i >= 0; --i)
       
   767 		{
       
   768 		if (iThreads[i].iOwningProcess == process.iDProcessAddress)
       
   769 			{
       
   770 			++process.iReferenceCount;
       
   771 			}
       
   772 		}
       
   773 
       
   774 	SeenAllThreadsL(process, aTickCount);
       
   775 	}
       
   776 
       
   777 void CBtraceContext::RemoveThread(TInt aPosition)
       
   778 	{
       
   779 	TProcess findKey(iThreads[aPosition].iOwningProcess);
       
   780 	TInt processPos = iProcesses.Find(findKey, TIdentityRelation<TProcess>(ProcessMatchesDProcessAddress));
       
   781 	if (processPos >= 0)
       
   782 		{
       
   783 		if (--(iProcesses[processPos].iReferenceCount) == 0)
       
   784 			{
       
   785 			iProcesses.Remove(processPos);
       
   786 			}
       
   787 		}
       
   788 	iThreads.Remove(aPosition);
       
   789 	}
       
   790 
       
   791 void CBtraceContext::SeenAllThreadsL(const TProcess& aProcess, const TBtraceTickCount& aTickCount)
       
   792 	{
       
   793 	// Call SeenL for each thread belonging to this process because. This is called when a process
       
   794 	// is created or altered because this change may allow a TThreadSeenNotif to be completed.
       
   795 	const TInt numThreads = iThreads.Count();
       
   796 	for (TInt i = 0; i < numThreads; ++i)
       
   797 		{
       
   798 		const TThread& thread = iThreads[i];
       
   799 		if (thread.iOwningProcess == aProcess.iDProcessAddress)
       
   800 			{
       
   801 			SeenL(thread, aTickCount);
       
   802 			}
       
   803 		}
       
   804 	}
       
   805 
       
   806 void CBtraceContext::BtraceBufferHasBeenReset()
       
   807 	{
       
   808 	iThreads.Close();
       
   809 	iProcesses.Close();
       
   810 	}
       
   811 
       
   812 CBtraceContext::TThread::TThread(TUint32 aNThreadAddress, TUint32 aOwningProcess, const TDesC8& aName)
       
   813 	: iNThreadAddress(aNThreadAddress), iOwningProcess(aOwningProcess), iKernelId(0)
       
   814 	{
       
   815 	iName.Copy(aName);
       
   816 	}
       
   817 
       
   818 CBtraceContext::TProcess::TProcess(TUint32 aDProcessAddress)
       
   819 	: iDProcessAddress(aDProcessAddress), iReferenceCount(0)
       
   820 	{
       
   821 	}
       
   822 
       
   823 CBtraceContext::TProcess::TProcess(TUint32 aDProcessAddress, const TDesC8& aName)
       
   824 	: iDProcessAddress(aDProcessAddress), iReferenceCount(0)
       
   825 	{
       
   826 	iName.Copy(aName);
       
   827 	}
       
   828 
       
   829 CBtraceContext::TWindowGroup::TWindowGroup(TInt aWindowGroupId)
       
   830 	: iWindowGroupId(aWindowGroupId), iThreadId(0)
       
   831 	{
       
   832 	}
       
   833 
       
   834 CBtraceContext::TWindowGroup::TWindowGroup(const TDesC& aName)
       
   835 	: iWindowGroupId(0), iThreadId(0), iName(aName)
       
   836 	{
       
   837 	}
       
   838 
       
   839 CBtraceContext::TWindowGroup::TWindowGroup(TInt aWindowGroupId, TThreadId aThreadId, const TDesC& aName)
       
   840 	: iWindowGroupId(aWindowGroupId), iThreadId(aThreadId), iName(aName)
       
   841 	{
       
   842 	}
       
   843 
       
   844 CBtraceContext::TThreadSeenNotif::TThreadSeenNotif(TUint aId, const TDesC& aPattern, MBtraceContextObserver& aObserver, TBtraceNotificationPersistence aPersistence)
       
   845 	: iId(aId), iPattern(aPattern), iObserver(aObserver), iPersistence(aPersistence)
       
   846 	{
       
   847 	}
       
   848 
       
   849 CBtraceContext::TThreadGoneNotif::TThreadGoneNotif(TUint aId, const TDesC& aPattern, MBtraceContextObserver& aObserver, TBtraceNotificationPersistence aPersistence)
       
   850 	: iId(aId), iPattern(aPattern), iObserver(aObserver), iPersistence(aPersistence)
       
   851 	{
       
   852 	}
       
   853 
       
   854 CBtraceContext::TThreadExitNotif::TThreadExitNotif(TUint aId, const TDesC& aPattern, TUint aExitTypes, TInt* aReason, const TDesC* aCategory, MBtraceContextObserver& aObserver, TBtraceNotificationPersistence aPersistence)
       
   855 	: iId(aId), iPattern(aPattern), iExitTypes(aExitTypes), iReason(aReason), iCategory(aCategory), iObserver(aObserver), iPersistence(aPersistence)
       
   856 	{
       
   857 	}
       
   858 
       
   859 CBtraceContext::TWindowGroupSeenNotif::TWindowGroupSeenNotif(TUint aId, const TDesC& aPattern, TPatternType aPatternType, MBtraceContextObserver& aObserver, TBtraceNotificationPersistence aPersistence)
       
   860 	: iId(aId), iPattern(aPattern), iPatternType(aPatternType), iObserver(aObserver), iPersistence(aPersistence)
       
   861 	{
       
   862 	}
       
   863 
       
   864 TBool CBtraceContext::TThreadExitNotif::Matches(const TDesC& aThreadName, TExitType aExitType, TInt aReason, const TDesC& aCategory) const
       
   865 	{
       
   866 	if (aThreadName.MatchF(iPattern) != KErrNotFound)
       
   867 		{
       
   868 		if (MatchesType(aExitType))
       
   869 			{
       
   870 			if ((iReason == NULL) || (*iReason == aReason))
       
   871 				{
       
   872 				if ((aExitType != EExitPanic) || ((iCategory == NULL) || (*iCategory == aCategory)))
       
   873 					{
       
   874 					return ETrue;
       
   875 					}
       
   876 				}
       
   877 			}
       
   878 		}
       
   879 	return EFalse;
       
   880 	}
       
   881 
       
   882 TBool CBtraceContext::TThreadExitNotif::MatchesType(TExitType aExitType) const
       
   883 	{
       
   884 	switch (aExitType)
       
   885 		{
       
   886 		case EExitKill:
       
   887 			return (iExitTypes & EKill);
       
   888 		case EExitTerminate:
       
   889 			return (iExitTypes & ETerminate);
       
   890 		case EExitPanic:
       
   891 			return (iExitTypes & EPanic);
       
   892 		default:
       
   893 			ASSERT(EFalse);
       
   894 			return EFalse;
       
   895 		}
       
   896 	}