SDL_Android/SmartDeviceLinkAndroidProxy - added the correct version of the proxy
[profile/ivi/smartdevicelink.git] / SDL_Android / SmartDeviceLinkProxyAndroid / src / com / smartdevicelink / trace / SmartDeviceLinkTrace.java
1 package com.smartdevicelink.trace;\r
2 \r
3 import java.sql.Timestamp;\r
4 \r
5 import android.bluetooth.BluetoothDevice;\r
6 import android.os.Build;\r
7 import android.os.Debug;\r
8 import android.os.Process;\r
9 \r
10 import com.smartdevicelink.protocol.ProtocolFrameHeader;\r
11 import com.smartdevicelink.protocol.enums.FrameDataControlFrameType;\r
12 import com.smartdevicelink.protocol.enums.FrameType;\r
13 import com.smartdevicelink.protocol.enums.SessionType;\r
14 import com.smartdevicelink.proxy.RPCMessage;\r
15 import com.smartdevicelink.proxy.RPCRequest;\r
16 import com.smartdevicelink.proxy.RPCResponse;\r
17 import com.smartdevicelink.trace.enums.DetailLevel;\r
18 import com.smartdevicelink.trace.enums.InterfaceActivityDirection;\r
19 import com.smartdevicelink.trace.enums.Mod;\r
20 import com.smartdevicelink.transport.SiphonServer;\r
21 import com.smartdevicelink.util.BitConverter;\r
22 import com.smartdevicelink.util.DebugTool;\r
23 import com.smartdevicelink.util.NativeLogTool;\r
24 \r
25 /* This class handles the global TraceSettings as requested by the users either through the combination of the following\r
26    1. System defaults\r
27    2. Application XML config\r
28    3. Programmatic requests from application itself\r
29 \r
30    It is manifested in the <applink>...</applink> tags\r
31  */\r
32 \r
33 public class SmartDeviceLinkTrace {\r
34         private static final String SMARTDEVICELINK_LIB_TRACE_KEY = "42baba60-eb57-11df-98cf-0800200c9a66";\r
35         \r
36         static boolean canWriteLogs = false;\r
37                 \r
38         public static final String SYSTEM_LOG_TAG = "SmartDeviceLinkTrace";\r
39         \r
40         private static long baseTics  = java.lang.System.currentTimeMillis();\r
41         private final static String KeyStr = SMARTDEVICELINK_LIB_TRACE_KEY;\r
42         private static boolean acceptAPITraceAdjustments = true;\r
43 \r
44         protected static ISTListener m_appTraceListener = null;\r
45 \r
46         ///\r
47         ///  The PUBLIC interface to SmartDeviceLinkTrace starts here\r
48         ///\r
49 \r
50 \r
51         public static void setAcceptAPITraceAdjustments(Boolean APITraceAdjustmentsAccepted) {\r
52                 if (APITraceAdjustmentsAccepted != null) {\r
53                         acceptAPITraceAdjustments = APITraceAdjustmentsAccepted;\r
54                 }\r
55         }\r
56         \r
57         public static boolean getAcceptAPITraceAdjustments() {\r
58                 return acceptAPITraceAdjustments;\r
59         }\r
60         \r
61         public static void setAppTraceListener(ISTListener listener) {\r
62                 m_appTraceListener = listener;\r
63         } // end-method\r
64 \r
65         public static void setTracingEnable(Boolean enable) {\r
66                 if (enable != null) {\r
67                         canWriteLogs = enable;\r
68                 }\r
69         } // end-method\r
70 \r
71         public static void setAppTraceLevel(DetailLevel dt) {\r
72                 if ( dt != null && acceptAPITraceAdjustments)\r
73                         DiagLevel.setLevel(Mod.app, dt);\r
74         } // end-method\r
75 \r
76         public static void setProxyTraceLevel(DetailLevel dt) {\r
77                 if (dt != null && acceptAPITraceAdjustments)\r
78                         DiagLevel.setLevel(Mod.proxy, dt);\r
79         } // end-method\r
80 \r
81         public static void setRpcTraceLevel(DetailLevel dt) {\r
82                 if (dt != null && acceptAPITraceAdjustments)\r
83                         DiagLevel.setLevel(Mod.rpc, dt);\r
84         } // end-method\r
85 \r
86         public static void setMarshallingTraceLevel(DetailLevel dt) {\r
87                 if (dt != null && acceptAPITraceAdjustments)\r
88                         DiagLevel.setLevel(Mod.mar, dt);\r
89         } // end-method\r
90 \r
91         public static void setProtocolTraceLevel(DetailLevel dt) {\r
92                 if (dt != null && acceptAPITraceAdjustments)\r
93                         DiagLevel.setLevel(Mod.proto, dt);\r
94         } // end-method\r
95 \r
96         public static void setTransportTraceLevel(DetailLevel dt) {\r
97                 if (dt != null && acceptAPITraceAdjustments)\r
98                                 DiagLevel.setLevel(Mod.tran, dt);\r
99         } // end-method\r
100 \r
101         private static String encodeTraceMessage(long timestamp, Mod module, InterfaceActivityDirection msgDirection, String msgBodyXml) {\r
102                 StringBuilder sb = new StringBuilder("<msg><dms>");\r
103                 sb.append(timestamp);\r
104                 sb.append("</dms><pid>");\r
105                 sb.append(Process.myPid());\r
106                 sb.append("</pid><tid>");\r
107                 sb.append(Thread.currentThread().getId());\r
108                 sb.append("</tid><mod>");\r
109                 sb.append(module.toString());\r
110                 sb.append("</mod>");\r
111                 if (msgDirection != InterfaceActivityDirection.None) {\r
112                         sb.append("<dir>");\r
113                         sb.append(interfaceActivityDirectionToString(msgDirection));\r
114                         sb.append("</dir>");\r
115                 } // end-if\r
116                 sb.append(msgBodyXml);\r
117                 sb.append("</msg>");\r
118 \r
119                 return sb.toString();\r
120         } // end-method\r
121 \r
122         private static String interfaceActivityDirectionToString(InterfaceActivityDirection iaDirection) {\r
123                 String str = "";\r
124                 switch (iaDirection) {\r
125                         case Receive:\r
126                                 str = "rx";\r
127                                 break;\r
128                         case Transmit:\r
129                                 str = "tx";\r
130                                 break;\r
131                 } // end-switch\r
132                 return str;\r
133         } // end-method\r
134 \r
135         static String B64EncodeForXML(String data) {\r
136                 return Mime.base64Encode(data);\r
137                 // Base64 only available in 2.2, when SmartDeviceLink base is 2.2 use: return Base64.encodeToString(data.getBytes(), Base64.DEFAULT);\r
138         } // end-method\r
139         \r
140         public static void logProxyEvent(String eventText, String token) {\r
141                 if (DiagLevel.getLevel(Mod.proxy) == DetailLevel.OFF || !token.equals(KeyStr)) {\r
142                         return;\r
143                 } // end-if\r
144 \r
145                 String msg = SmartDeviceLinkTrace.B64EncodeForXML(eventText);\r
146                 String xml = SmartDeviceLinkTrace.encodeTraceMessage(SmartDeviceLinkTrace.getBaseTicsDelta(), Mod.proxy, InterfaceActivityDirection.None, "<d>" + msg + "</d>");\r
147                 writeXmlTraceMessage(xml);\r
148         } // end-method\r
149 \r
150         public static void logAppEvent(String eventText) {\r
151                 if (DiagLevel.getLevel(Mod.app) == DetailLevel.OFF) {\r
152                         return;\r
153                 } // end-if\r
154 \r
155                 long timestamp = SmartDeviceLinkTrace.getBaseTicsDelta();\r
156                 String msg = SmartDeviceLinkTrace.B64EncodeForXML(eventText);\r
157                 String xml = SmartDeviceLinkTrace.encodeTraceMessage(timestamp, Mod.app, InterfaceActivityDirection.None, "<d>" + msg + "</d>");\r
158                 writeXmlTraceMessage(xml);\r
159         } // end-method\r
160 \r
161         public static void logRPCEvent(InterfaceActivityDirection msgDirection, RPCMessage rpcMsg, String token) {\r
162                 DetailLevel dl = DiagLevel.getLevel(Mod.rpc);\r
163                 if (dl == DetailLevel.OFF || !token.equals(KeyStr)) {\r
164                         return;\r
165                 } // end-if\r
166 \r
167                 long timestamp = SmartDeviceLinkTrace.getBaseTicsDelta();\r
168                 String xml = SmartDeviceLinkTrace.encodeTraceMessage(timestamp, Mod.rpc, msgDirection, rpc2Xml(dl, rpcMsg));\r
169                 writeXmlTraceMessage(xml);\r
170         } // end-method\r
171 \r
172         private static String rpc2Xml(DetailLevel dl, RPCMessage rpcMsg) {\r
173                 StringBuilder rpcAsXml = new StringBuilder();\r
174                 rpcAsXml.append("<op>");\r
175                 rpcAsXml.append(rpcMsg.getFunctionName());\r
176                 rpcAsXml.append("</op>");\r
177                 boolean hasCorrelationID = false;\r
178                 Integer correlationID = -1;\r
179                 if (rpcMsg instanceof RPCRequest) {\r
180                         hasCorrelationID = true;\r
181                         correlationID = ((RPCRequest)rpcMsg).getCorrelationID();\r
182                 } else if (rpcMsg instanceof RPCResponse) {\r
183                         hasCorrelationID = true;\r
184                         correlationID = ((RPCResponse)rpcMsg).getCorrelationID();\r
185                 } // end-if\r
186                 if (hasCorrelationID) {\r
187                         rpcAsXml.append("<cid>");\r
188                         rpcAsXml.append(correlationID);\r
189                         rpcAsXml.append("</cid>");\r
190                 } // end-if\r
191                 rpcAsXml.append("<type>");\r
192                 rpcAsXml.append(rpcMsg.getMessageType());\r
193                 rpcAsXml.append("</type>");\r
194                 //rpcAsXml.append(newline);\r
195 \r
196                 if (dl == DetailLevel.VERBOSE) {\r
197                         OpenRPCMessage orpcmsg = new OpenRPCMessage(rpcMsg);\r
198                         String rpcParamList = orpcmsg.msgDump();\r
199                         String msg = SmartDeviceLinkTrace.B64EncodeForXML(rpcParamList);\r
200                         rpcAsXml.append("<d>");\r
201                         rpcAsXml.append(msg);\r
202                         rpcAsXml.append("</d>");\r
203                 } // end-if\r
204                 return rpcAsXml.toString();\r
205         } // end-method\r
206 \r
207         public static void logMarshallingEvent(InterfaceActivityDirection msgDirection, byte[] marshalledMessage, String token) {\r
208                 DetailLevel dl = DiagLevel.getLevel(Mod.mar);\r
209                 if (dl == DetailLevel.OFF || !token.equals(KeyStr)) {\r
210                         return;\r
211                 } // end-fif\r
212 \r
213                 long timestamp = SmartDeviceLinkTrace.getBaseTicsDelta();\r
214                 StringBuilder msg = new StringBuilder();\r
215                 msg.append("<sz>");\r
216                 msg.append(marshalledMessage.length);\r
217                 msg.append("</sz>");\r
218                 if (dl == DetailLevel.VERBOSE) {\r
219                         msg.append("<d>");\r
220                         msg.append(Mime.base64Encode(marshalledMessage));\r
221                         // Base64 only available in 2.2, when SmartDeviceLink base is 2.2 use: msg.append(Base64.encodeToString(marshalledMessage, Base64.DEFAULT));\r
222                         msg.append("</d>");\r
223                 } // end-if\r
224                 String xml = SmartDeviceLinkTrace.encodeTraceMessage(timestamp, Mod.mar, msgDirection, msg.toString());\r
225                 writeXmlTraceMessage(xml);\r
226         } // end-method\r
227 \r
228         public static void logProtocolEvent(InterfaceActivityDirection frameDirection, ProtocolFrameHeader frameHeader, byte[] frameData, int frameDataOffset, int frameDataLength, String token) {\r
229                 DetailLevel dl = DiagLevel.getLevel(Mod.proto);\r
230                 if (dl == DetailLevel.OFF || !token.equals(KeyStr)) {\r
231                         return;\r
232                 } // end-if\r
233 \r
234                 StringBuffer protoMsg = new StringBuffer();\r
235                 protoMsg.append("<frame>");\r
236                 protoMsg.append(SmartDeviceLinkTrace.getProtocolFrameHeaderInfo(frameHeader, frameData));\r
237                 if (dl == DetailLevel.VERBOSE) {\r
238                         if (frameData != null && frameDataLength > 0) {\r
239                                 protoMsg.append("<d>");\r
240                                 String bytesInfo = "";\r
241                                 bytesInfo = Mime.base64Encode(frameData, frameDataOffset, frameDataLength);\r
242                                 // Base64 only available in 2.2, when SmartDeviceLink base is 2.2 use: bytesInfo = Base64.encodeToString(frameData, frameDataOffset, frameDataLength, Base64.DEFAULT);\r
243                                 protoMsg.append(bytesInfo);\r
244                                 protoMsg.append("</d>");\r
245                         } // end-if\r
246                 } // end-if\r
247                 protoMsg.append("</frame>");\r
248                 String xml = SmartDeviceLinkTrace.encodeTraceMessage(SmartDeviceLinkTrace.getBaseTicsDelta(), Mod.proto, frameDirection, protoMsg.toString());\r
249                 writeXmlTraceMessage(xml);\r
250         } // end-method\r
251 \r
252         private static String getProtocolFrameType(FrameType f) {\r
253                 if (f == FrameType.Control)\r
254                         return "Control";\r
255                 else if (f == FrameType.Consecutive)\r
256                         return "Consecutive";\r
257                 else if (f == FrameType.First)\r
258                         return "First";\r
259                 else if (f == FrameType.Single)\r
260                         return "Single";\r
261 \r
262                 return "Unknown";\r
263         } // end-method\r
264 \r
265         private static String getProtocolSessionType(SessionType serviceType) {\r
266                 String s;\r
267                 if (serviceType == SessionType.RPC )\r
268                         s = "rpc";\r
269                 else if (serviceType == SessionType.Bulk_Data)\r
270                         s = "bulk";\r
271                 else\r
272                         s = "Unknown";\r
273                 return s;\r
274         } // end-method\r
275 \r
276         private static String getProtocolFrameHeaderInfo(ProtocolFrameHeader hdr, byte[] buf) {\r
277                 StringBuilder sb = new StringBuilder();\r
278                 sb.append("<hdr>");\r
279                 sb.append("<ver>");\r
280                 sb.append(hdr.getVersion());\r
281                 sb.append("</ver><cmp>");\r
282                 sb.append(hdr.isCompressed());\r
283                 sb.append("</cmp><ft>");\r
284                 sb.append(getProtocolFrameType(hdr.getFrameType()));\r
285                 sb.append("</ft><st>");\r
286                 sb.append(getProtocolSessionType(hdr.getSessionType()));\r
287                 sb.append("</st><sid>");\r
288                 sb.append(hdr.getSessionID());\r
289                 sb.append("</sid><sz>");\r
290                 sb.append(hdr.getDataSize());\r
291                 sb.append("</sz>");\r
292 \r
293                 int frameData = hdr.getFrameData();\r
294                 if (hdr.getFrameType() == FrameType.Control) {\r
295                         sb.append("<ca>");\r
296                         if (frameData == FrameDataControlFrameType.StartSession.getValue()) \r
297                                 sb.append("StartSession");\r
298                         else if (frameData == FrameDataControlFrameType.StartSessionACK.getValue())\r
299                                 sb.append("StartSessionACK");\r
300                         else if (frameData == FrameDataControlFrameType.StartSessionNACK.getValue())\r
301                                 sb.append("StartSessionNACK");\r
302                         else if (frameData == FrameDataControlFrameType.EndSession.getValue())\r
303                                 sb.append("EndSession");\r
304                         sb.append("</ca>");\r
305                 } else if (hdr.getFrameType() == FrameType.Consecutive ) {\r
306                         sb.append("<fsn>");\r
307                         if (frameData == 0 )\r
308                                 sb.append("lastFrame");\r
309                         else\r
310                                 sb.append(String.format("%02X",frameData)); \r
311                         sb.append("</fsn>");\r
312                 } else if (hdr.getFrameType() == FrameType.First ) {\r
313                         int totalSize = BitConverter.intFromByteArray(buf, 0);                  \r
314                         int numFrames = BitConverter.intFromByteArray(buf, 4);\r
315                         sb.append("<total>" + totalSize + "</total><numframes>" + numFrames + "</numframes>");\r
316                 } else if (hdr.getFrameType() == FrameType.Single ) {\r
317                         sb.append("<single/>");\r
318                 }\r
319 \r
320                 sb.append("</hdr>");\r
321 \r
322                 return sb.toString();\r
323         } // end-method\r
324 \r
325         public static String getBTDeviceInfo(BluetoothDevice btDevice) {\r
326                 StringBuilder sb = new StringBuilder();\r
327                 sb.append("<btp>");\r
328                 String btdn = btDevice.getName();\r
329                 sb.append("<btn>");\r
330                 sb.append(SmartDeviceLinkTrace.B64EncodeForXML(btdn));\r
331                 sb.append("</btn>");\r
332                 sb.append("<bta>" + btDevice.getAddress() + "</bta>");\r
333                 sb.append("<bts>" + btDevice.getBondState() + "</bts>");\r
334                 sb.append("</btp>");\r
335                 return sb.toString();\r
336         } // end-method\r
337 \r
338         public static void logTransportEvent(String preamble, String transportSpecificInfoXml, InterfaceActivityDirection msgDirection, byte buf[], int byteLength, String token) {\r
339                 logTransportEvent(preamble, transportSpecificInfoXml, msgDirection, buf, 0, byteLength, token);\r
340         } // end-method\r
341 \r
342         private static void checkB64(String x, byte[] buf, int offset, int byteLength) {\r
343                 if ((x.length() % 4) != 0) {\r
344                         NativeLogTool.logWarning(SmartDeviceLinkTrace.SYSTEM_LOG_TAG, "b64 string length (" + x.length() + ") isn't multiple of 4: buf.length=" + buf.length + ", offset=" + offset + ", len=" + byteLength);\r
345                 } // end-if\r
346         } // end-method\r
347 \r
348         public static void logTransportEvent(String preamble, String transportSpecificInfoXml, InterfaceActivityDirection msgDirection, byte buf[], int offset, int byteLength, String token) {\r
349                 if (DiagLevel.getLevel(Mod.tran) == DetailLevel.OFF || !token.equals(KeyStr)) {\r
350                         return;\r
351                 } // end-if\r
352 \r
353                 StringBuilder msg = new StringBuilder();\r
354                 if (transportSpecificInfoXml != null && transportSpecificInfoXml.length() > 0) {\r
355                         msg.append(transportSpecificInfoXml);\r
356                 } // end-if\r
357                 if (preamble != null && preamble.length() > 0) {\r
358                         msg.append("<desc>");\r
359                         msg.append(preamble);\r
360                         msg.append("</desc>");\r
361                 } // end-if\r
362                 if (buf != null) {\r
363                         msg.append("<sz>");\r
364                         msg.append(byteLength);\r
365                         msg.append("</sz>");\r
366                         DetailLevel dl = DiagLevel.getLevel(Mod.tran);\r
367                         if (dl == DetailLevel.VERBOSE) {\r
368                                 if (buf != null && byteLength > 0) {\r
369                                         msg.append("<d>");\r
370                                         String bytesInfo = Mime.base64Encode(buf, offset, byteLength);\r
371                                         checkB64(bytesInfo, buf, offset, byteLength);\r
372                                         msg.append(bytesInfo);\r
373                                         msg.append("</d>");\r
374                                 } // end-if\r
375                         } // end-if\r
376                 } // end-if\r
377                 String xml = SmartDeviceLinkTrace.encodeTraceMessage(SmartDeviceLinkTrace.getBaseTicsDelta(), Mod.tran, msgDirection, msg.toString());\r
378                 writeXmlTraceMessage(xml);\r
379         } // end-method\r
380 \r
381         // Package-scoped\r
382         static long getBaseTicsDelta() {\r
383                 return java.lang.System.currentTimeMillis() - getBaseTics();\r
384         }\r
385 \r
386         // Package-scoped\r
387         static long getBaseTics() {\r
388                 return baseTics;\r
389         } // end-method\r
390 \r
391         public static Boolean writeMessageToSiphonServer(String info) {\r
392                 return SiphonServer.sendFormattedTraceMessage(info);\r
393         }\r
394 \r
395         private static void writeXmlTraceMessage(String msg) {\r
396                 try {                   \r
397                         // Attempt to write formatted message to the Siphon\r
398                         if (false == writeMessageToSiphonServer(msg)) {\r
399                                 // If writing to the Siphon fails, write to the native log\r
400                                 NativeLogTool.logInfo(SmartDeviceLinkTrace.SYSTEM_LOG_TAG, msg);\r
401                         }\r
402                         \r
403                         ISTListener localTraceListener = m_appTraceListener;\r
404 \r
405                         if (localTraceListener != null) {\r
406                                 try {\r
407                                         localTraceListener.logXmlMsg(msg, KeyStr);\r
408                                 } catch (Exception ex) {\r
409                                         DebugTool.logError("Failure calling ISTListener: " + ex.toString(), ex);\r
410                                 } // end-catch\r
411                         } // end-if\r
412                 } catch (Exception ex) {\r
413                         NativeLogTool.logError(SmartDeviceLinkTrace.SYSTEM_LOG_TAG, "Failure writing XML trace message: " + ex.toString());\r
414                 }\r
415         } // end-method\r
416         \r
417         // Package-scoped\r
418         public static String getLogHeader(String dumpReason, int seqNo) {\r
419                 final String Sep = "-";\r
420                 StringBuilder write = new StringBuilder("<?xml version=\"1.0\"?>" + "<logs>");\r
421                 write.append("<info>");\r
422                 StringBuilder infoBlock = new StringBuilder();\r
423                 String hostInfo = Build.BRAND + Sep + Build.MANUFACTURER + Sep + Build.MODEL + "(" + Build.HOST + ")";\r
424                 infoBlock.append("<host>" + SmartDeviceLinkTrace.B64EncodeForXML(hostInfo) + "</host>");\r
425                 String osv = Build.VERSION.RELEASE + " (" + Build.VERSION.CODENAME + ")";\r
426                 infoBlock.append("<osv>" + SmartDeviceLinkTrace.B64EncodeForXML(osv) + "</osv>");\r
427                 infoBlock.append(TraceDeviceInfo.getTelephonyHeader());\r
428 \r
429                 long heapSize = Debug.getNativeHeapFreeSize() / 1024;\r
430                 long heapAllocated = Debug.getNativeHeapAllocatedSize() / 1024;\r
431                 infoBlock.append("<mem><hf>" + heapSize + "KB</hf><ha>" + heapAllocated + "KB</ha></mem>");\r
432                 infoBlock.append("<np>" + Runtime.getRuntime().availableProcessors() + "</np>");\r
433                 infoBlock.append("<pid>" + Process.myPid() + "</pid>");\r
434                 infoBlock.append("<tid>" + Thread.currentThread().getId() + "</tid>");\r
435 \r
436                 // String dateStamp = (String)\r
437                 // DateFormat.format("yy-MM-dd hh:mm:ss SSS", new Timestamp(baseTics));\r
438                 Timestamp stamp = new Timestamp(SmartDeviceLinkTrace.getBaseTics());\r
439                 String GMTtime = stamp.toGMTString().substring(0, 19);\r
440                 long fracSec = stamp.getNanos() / 1000000; // divide by a million\r
441                 String fracSecStr = String.format("%03d", fracSec);\r
442                 infoBlock.append("<utc>" + GMTtime + "." + fracSecStr + "</utc>");\r
443 \r
444                 infoBlock.append(TraceDeviceInfo.getLogHeaderBluetoothPairs());\r
445                 infoBlock.append(getApplinkTraceRoot(dumpReason, seqNo));\r
446 \r
447                 write.append(infoBlock);\r
448 \r
449                 write.append("</info>" + "<msgs>");\r
450                 return write.toString();\r
451         } // end-method\r
452         \r
453         private static String getApplinkTraceRoot(String dumpReason, int seqNo) {\r
454                 StringBuilder write = new StringBuilder("<applinktraceroot>" + "<sequencenum>" + seqNo\r
455                                 + "</sequencenum>" + "<dumpreason>" + dumpReason\r
456                                 + "</dumpreason><tracelevel>");\r
457 \r
458                 write.append("<tran>" + DiagLevel.getLevel(Mod.tran) + "</tran>");\r
459                 write.append("<proto>" + DiagLevel.getLevel(Mod.proto) + "</proto>");\r
460                 write.append("<mar>" + DiagLevel.getLevel(Mod.mar) + "</mar>");\r
461                 write.append("<rpc>" + DiagLevel.getLevel(Mod.rpc) + "</rpc>");\r
462                 write.append("<proxy>" + DiagLevel.getLevel(Mod.proxy) + "</proxy>");\r
463                 write.append("<app>" + DiagLevel.getLevel(Mod.app) + "</app>");\r
464 \r
465                 write.append("</tracelevel>");\r
466                 write.append("</applinktraceroot>");\r
467                 return write.toString();\r
468         } // end-method\r
469 } // end-class