-//
-// Copyright (c) 2013 Ford Motor Company
-//
-package com.smartdevicelink.trace;
-
-import java.sql.Timestamp;
-
-import android.bluetooth.BluetoothDevice;
-import android.os.Build;
-import android.os.Debug;
-import android.os.Process;
-
-import com.smartdevicelink.protocol.ProtocolFrameHeader;
-import com.smartdevicelink.protocol.enums.FrameDataControlFrameType;
-import com.smartdevicelink.protocol.enums.FrameType;
-import com.smartdevicelink.protocol.enums.SessionType;
-import com.smartdevicelink.proxy.RPCMessage;
-import com.smartdevicelink.proxy.RPCRequest;
-import com.smartdevicelink.proxy.RPCResponse;
-import com.smartdevicelink.trace.enums.DetailLevel;
-import com.smartdevicelink.trace.enums.InterfaceActivityDirection;
-import com.smartdevicelink.trace.enums.Mod;
-import com.smartdevicelink.transport.SiphonServer;
-import com.smartdevicelink.util.BitConverter;
-import com.smartdevicelink.util.DebugTool;
-import com.smartdevicelink.util.NativeLogTool;
-
-/* This class handles the global TraceSettings as requested by the users either through the combination of the following
- 1. System defaults
- 2. Application XML config
- 3. Programmatic requests from application itself
-
- It is manifested in the <SmartDeviceLink>...</SmartDeviceLink> tags
- */
-
-public class SyncTrace {
- private static final String SmartDeviceLink_LIB_TRACE_KEY = "42baba60-eb57-11df-98cf-0800200c9a66";
-
- static boolean canWriteLogs = false;
-
- public static final String SYSTEM_LOG_TAG = "SyncTrace";
-
- private static long baseTics = java.lang.System.currentTimeMillis();
- private final static String KeyStr = SmartDeviceLink_LIB_TRACE_KEY;
- private static boolean acceptAPITraceAdjustments = true;
-
- protected static ISTListener m_appTraceListener = null;
-
- ///
- /// The PUBLIC interface to SyncTrace starts here
- ///
-
-
- public static void setAcceptAPITraceAdjustments(Boolean APITraceAdjustmentsAccepted) {
- if (APITraceAdjustmentsAccepted != null) {
- acceptAPITraceAdjustments = APITraceAdjustmentsAccepted;
- }
- }
-
- public static boolean getAcceptAPITraceAdjustments() {
- return acceptAPITraceAdjustments;
- }
-
- public static void setAppTraceListener(ISTListener listener) {
- m_appTraceListener = listener;
- } // end-method
-
- public static void setTracingEnable(Boolean enable) {
- if (enable != null) {
- canWriteLogs = enable;
- }
- } // end-method
-
- public static void setAppTraceLevel(DetailLevel dt) {
- if ( dt != null && acceptAPITraceAdjustments)
- DiagLevel.setLevel(Mod.app, dt);
- } // end-method
-
- public static void setProxyTraceLevel(DetailLevel dt) {
- if (dt != null && acceptAPITraceAdjustments)
- DiagLevel.setLevel(Mod.proxy, dt);
- } // end-method
-
- public static void setRpcTraceLevel(DetailLevel dt) {
- if (dt != null && acceptAPITraceAdjustments)
- DiagLevel.setLevel(Mod.rpc, dt);
- } // end-method
-
- public static void setMarshallingTraceLevel(DetailLevel dt) {
- if (dt != null && acceptAPITraceAdjustments)
- DiagLevel.setLevel(Mod.mar, dt);
- } // end-method
-
- public static void setProtocolTraceLevel(DetailLevel dt) {
- if (dt != null && acceptAPITraceAdjustments)
- DiagLevel.setLevel(Mod.proto, dt);
- } // end-method
-
- public static void setTransportTraceLevel(DetailLevel dt) {
- if (dt != null && acceptAPITraceAdjustments)
- DiagLevel.setLevel(Mod.tran, dt);
- } // end-method
-
- private static String encodeTraceMessage(long timestamp, Mod module, InterfaceActivityDirection msgDirection, String msgBodyXml) {
- StringBuilder sb = new StringBuilder("<msg><dms>");
- sb.append(timestamp);
- sb.append("</dms><pid>");
- sb.append(Process.myPid());
- sb.append("</pid><tid>");
- sb.append(Thread.currentThread().getId());
- sb.append("</tid><mod>");
- sb.append(module.toString());
- sb.append("</mod>");
- if (msgDirection != InterfaceActivityDirection.None) {
- sb.append("<dir>");
- sb.append(interfaceActivityDirectionToString(msgDirection));
- sb.append("</dir>");
- } // end-if
- sb.append(msgBodyXml);
- sb.append("</msg>");
-
- return sb.toString();
- } // end-method
-
- private static String interfaceActivityDirectionToString(InterfaceActivityDirection iaDirection) {
- String str = "";
- switch (iaDirection) {
- case Receive:
- str = "rx";
- break;
- case Transmit:
- str = "tx";
- break;
- } // end-switch
- return str;
- } // end-method
-
- static String B64EncodeForXML(String data) {
- return Mime.base64Encode(data);
- } // end-method
-
- public static void logProxyEvent(String eventText, String token) {
- if (DiagLevel.getLevel(Mod.proxy) == DetailLevel.OFF || !token.equals(KeyStr)) {
- return;
- } // end-if
-
- String msg = SyncTrace.B64EncodeForXML(eventText);
- String xml = SyncTrace.encodeTraceMessage(SyncTrace.getBaseTicsDelta(), Mod.proxy, InterfaceActivityDirection.None, "<d>" + msg + "</d>");
- writeXmlTraceMessage(xml);
- } // end-method
-
- public static void logAppEvent(String eventText) {
- if (DiagLevel.getLevel(Mod.app) == DetailLevel.OFF) {
- return;
- } // end-if
-
- long timestamp = SyncTrace.getBaseTicsDelta();
- String msg = SyncTrace.B64EncodeForXML(eventText);
- String xml = SyncTrace.encodeTraceMessage(timestamp, Mod.app, InterfaceActivityDirection.None, "<d>" + msg + "</d>");
- writeXmlTraceMessage(xml);
- } // end-method
-
- public static void logRPCEvent(InterfaceActivityDirection msgDirection, RPCMessage rpcMsg, String token) {
- DetailLevel dl = DiagLevel.getLevel(Mod.rpc);
- if (dl == DetailLevel.OFF || !token.equals(KeyStr)) {
- return;
- } // end-if
-
- long timestamp = SyncTrace.getBaseTicsDelta();
- String xml = SyncTrace.encodeTraceMessage(timestamp, Mod.rpc, msgDirection, rpc2Xml(dl, rpcMsg));
- writeXmlTraceMessage(xml);
- } // end-method
-
- private static String rpc2Xml(DetailLevel dl, RPCMessage rpcMsg) {
- StringBuilder rpcAsXml = new StringBuilder();
- rpcAsXml.append("<op>");
- rpcAsXml.append(rpcMsg.getFunctionName());
- rpcAsXml.append("</op>");
- boolean hasCorrelationID = false;
- Integer correlationID = -1;
- if (rpcMsg instanceof RPCRequest) {
- hasCorrelationID = true;
- correlationID = ((RPCRequest)rpcMsg).getCorrelationID();
- } else if (rpcMsg instanceof RPCResponse) {
- hasCorrelationID = true;
- correlationID = ((RPCResponse)rpcMsg).getCorrelationID();
- } // end-if
- if (hasCorrelationID) {
- rpcAsXml.append("<cid>");
- rpcAsXml.append(correlationID);
- rpcAsXml.append("</cid>");
- } // end-if
- rpcAsXml.append("<type>");
- rpcAsXml.append(rpcMsg.getMessageType());
- rpcAsXml.append("</type>");
-
- if (dl == DetailLevel.VERBOSE) {
- OpenRPCMessage orpcmsg = new OpenRPCMessage(rpcMsg);
- String rpcParamList = orpcmsg.msgDump();
- String msg = SyncTrace.B64EncodeForXML(rpcParamList);
- rpcAsXml.append("<d>");
- rpcAsXml.append(msg);
- rpcAsXml.append("</d>");
- } // end-if
- return rpcAsXml.toString();
- } // end-method
-
- public static void logMarshallingEvent(InterfaceActivityDirection msgDirection, byte[] marshalledMessage, String token) {
- DetailLevel dl = DiagLevel.getLevel(Mod.mar);
- if (dl == DetailLevel.OFF || !token.equals(KeyStr)) {
- return;
- } // end-fif
-
- long timestamp = SyncTrace.getBaseTicsDelta();
- StringBuilder msg = new StringBuilder();
- msg.append("<sz>");
- msg.append(marshalledMessage.length);
- msg.append("</sz>");
- if (dl == DetailLevel.VERBOSE) {
- msg.append("<d>");
- msg.append(Mime.base64Encode(marshalledMessage));
- msg.append("</d>");
- } // end-if
- String xml = SyncTrace.encodeTraceMessage(timestamp, Mod.mar, msgDirection, msg.toString());
- writeXmlTraceMessage(xml);
- } // end-method
-
- public static void logProtocolEvent(InterfaceActivityDirection frameDirection, ProtocolFrameHeader frameHeader, byte[] frameData, int frameDataOffset, int frameDataLength, String token) {
- DetailLevel dl = DiagLevel.getLevel(Mod.proto);
- if (dl == DetailLevel.OFF || !token.equals(KeyStr)) {
- return;
- } // end-if
-
- StringBuffer protoMsg = new StringBuffer();
- protoMsg.append("<frame>");
- protoMsg.append(SyncTrace.getProtocolFrameHeaderInfo(frameHeader, frameData));
- if (dl == DetailLevel.VERBOSE) {
- if (frameData != null && frameDataLength > 0) {
- protoMsg.append("<d>");
- String bytesInfo = "";
- bytesInfo = Mime.base64Encode(frameData, frameDataOffset, frameDataLength);
- protoMsg.append(bytesInfo);
- protoMsg.append("</d>");
- } // end-if
- } // end-if
- protoMsg.append("</frame>");
- String xml = SyncTrace.encodeTraceMessage(SyncTrace.getBaseTicsDelta(), Mod.proto, frameDirection, protoMsg.toString());
- writeXmlTraceMessage(xml);
- } // end-method
-
- private static String getProtocolFrameType(FrameType f) {
- if (f == FrameType.Control)
- return "Control";
- else if (f == FrameType.Consecutive)
- return "Consecutive";
- else if (f == FrameType.First)
- return "First";
- else if (f == FrameType.Single)
- return "Single";
-
- return "Unknown";
- } // end-method
-
- private static String getProtocolSessionType(SessionType serviceType) {
- String s;
- if (serviceType == SessionType.RPC )
- s = "rpc";
- else if (serviceType == SessionType.Bulk_Data)
- s = "bulk";
- else
- s = "Unknown";
- return s;
- } // end-method
-
- private static String getProtocolFrameHeaderInfo(ProtocolFrameHeader hdr, byte[] buf) {
- StringBuilder sb = new StringBuilder();
- sb.append("<hdr>");
- sb.append("<ver>");
- sb.append(hdr.getVersion());
- sb.append("</ver><cmp>");
- sb.append(hdr.isCompressed());
- sb.append("</cmp><ft>");
- sb.append(getProtocolFrameType(hdr.getFrameType()));
- sb.append("</ft><st>");
- sb.append(getProtocolSessionType(hdr.getSessionType()));
- sb.append("</st><sid>");
- sb.append(hdr.getSessionID());
- sb.append("</sid><sz>");
- sb.append(hdr.getDataSize());
- sb.append("</sz>");
-
- int frameData = hdr.getFrameData();
- if (hdr.getFrameType() == FrameType.Control) {
- sb.append("<ca>");
- if (frameData == FrameDataControlFrameType.StartSession.getValue())
- sb.append("StartSession");
- else if (frameData == FrameDataControlFrameType.StartSessionACK.getValue())
- sb.append("StartSessionACK");
- else if (frameData == FrameDataControlFrameType.StartSessionNACK.getValue())
- sb.append("StartSessionNACK");
- else if (frameData == FrameDataControlFrameType.EndSession.getValue())
- sb.append("EndSession");
- sb.append("</ca>");
- } else if (hdr.getFrameType() == FrameType.Consecutive ) {
- sb.append("<fsn>");
- if (frameData == 0 )
- sb.append("lastFrame");
- else
- sb.append(String.format("%02X",frameData));
- sb.append("</fsn>");
- } else if (hdr.getFrameType() == FrameType.First ) {
- int totalSize = BitConverter.intFromByteArray(buf, 0);
- int numFrames = BitConverter.intFromByteArray(buf, 4);
- sb.append("<total>" + totalSize + "</total><numframes>" + numFrames + "</numframes>");
- } else if (hdr.getFrameType() == FrameType.Single ) {
- sb.append("<single/>");
- }
-
- sb.append("</hdr>");
-
- return sb.toString();
- } // end-method
-
- public static String getBTDeviceInfo(BluetoothDevice btDevice) {
- StringBuilder sb = new StringBuilder();
- sb.append("<btp>");
- String btdn = btDevice.getName();
- sb.append("<btn>");
- sb.append(SyncTrace.B64EncodeForXML(btdn));
- sb.append("</btn>");
- sb.append("<bta>" + btDevice.getAddress() + "</bta>");
- sb.append("<bts>" + btDevice.getBondState() + "</bts>");
- sb.append("</btp>");
- return sb.toString();
- } // end-method
-
- public static void logTransportEvent(String preamble, String transportSpecificInfoXml, InterfaceActivityDirection msgDirection, byte buf[], int byteLength, String token) {
- logTransportEvent(preamble, transportSpecificInfoXml, msgDirection, buf, 0, byteLength, token);
- } // end-method
-
- private static void checkB64(String x, byte[] buf, int offset, int byteLength) {
- if ((x.length() % 4) != 0) {
- NativeLogTool.logWarning(SyncTrace.SYSTEM_LOG_TAG, "b64 string length (" + x.length() + ") isn't multiple of 4: buf.length=" + buf.length + ", offset=" + offset + ", len=" + byteLength);
- } // end-if
- } // end-method
-
- public static void logTransportEvent(String preamble, String transportSpecificInfoXml, InterfaceActivityDirection msgDirection, byte buf[], int offset, int byteLength, String token) {
- if (DiagLevel.getLevel(Mod.tran) == DetailLevel.OFF || !token.equals(KeyStr)) {
- return;
- } // end-if
-
- StringBuilder msg = new StringBuilder();
- if (transportSpecificInfoXml != null && transportSpecificInfoXml.length() > 0) {
- msg.append(transportSpecificInfoXml);
- } // end-if
- if (preamble != null && preamble.length() > 0) {
- msg.append("<desc>");
- msg.append(preamble);
- msg.append("</desc>");
- } // end-if
- if (buf != null) {
- msg.append("<sz>");
- msg.append(byteLength);
- msg.append("</sz>");
- DetailLevel dl = DiagLevel.getLevel(Mod.tran);
- if (dl == DetailLevel.VERBOSE) {
- if (buf != null && byteLength > 0) {
- msg.append("<d>");
- String bytesInfo = Mime.base64Encode(buf, offset, byteLength);
- checkB64(bytesInfo, buf, offset, byteLength);
- msg.append(bytesInfo);
- msg.append("</d>");
- } // end-if
- } // end-if
- } // end-if
- String xml = SyncTrace.encodeTraceMessage(SyncTrace.getBaseTicsDelta(), Mod.tran, msgDirection, msg.toString());
- writeXmlTraceMessage(xml);
- } // end-method
-
- // Package-scoped
- static long getBaseTicsDelta() {
- return java.lang.System.currentTimeMillis() - getBaseTics();
- }
-
- // Package-scoped
- static long getBaseTics() {
- return baseTics;
- } // end-method
-
- public static Boolean writeMessageToSiphonServer(String info) {
- return SiphonServer.sendFormattedTraceMessage(info);
- }
-
- private static void writeXmlTraceMessage(String msg) {
- try {
- // Attempt to write formatted message to the Siphon
- if (false == writeMessageToSiphonServer(msg)) {
- // If writing to the Siphon fails, write to the native log
- NativeLogTool.logInfo(SyncTrace.SYSTEM_LOG_TAG, msg);
- }
-
- ISTListener localTraceListener = m_appTraceListener;
-
- if (localTraceListener != null) {
- try {
- localTraceListener.logXmlMsg(msg, KeyStr);
- } catch (Exception ex) {
- DebugTool.logError("Failure calling ISTListener: " + ex.toString(), ex);
- } // end-catch
- } // end-if
- } catch (Exception ex) {
- NativeLogTool.logError(SyncTrace.SYSTEM_LOG_TAG, "Failure writing XML trace message: " + ex.toString());
- }
- } // end-method
-
- // Package-scoped
- public static String getLogHeader(String dumpReason, int seqNo) {
- final String Sep = "-";
- StringBuilder write = new StringBuilder("<?xml version=\"1.0\"?>" + "<logs>");
- write.append("<info>");
- StringBuilder infoBlock = new StringBuilder();
- String hostInfo = Build.BRAND + Sep + Build.MANUFACTURER + Sep + Build.MODEL + "(" + Build.HOST + ")";
- infoBlock.append("<host>" + SyncTrace.B64EncodeForXML(hostInfo) + "</host>");
- String osv = Build.VERSION.RELEASE + " (" + Build.VERSION.CODENAME + ")";
- infoBlock.append("<osv>" + SyncTrace.B64EncodeForXML(osv) + "</osv>");
- infoBlock.append(TraceDeviceInfo.getTelephonyHeader());
-
- long heapSize = Debug.getNativeHeapFreeSize() / 1024;
- long heapAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
- infoBlock.append("<mem><hf>" + heapSize + "KB</hf><ha>" + heapAllocated + "KB</ha></mem>");
- infoBlock.append("<np>" + Runtime.getRuntime().availableProcessors() + "</np>");
- infoBlock.append("<pid>" + Process.myPid() + "</pid>");
- infoBlock.append("<tid>" + Thread.currentThread().getId() + "</tid>");
-
- Timestamp stamp = new Timestamp(SyncTrace.getBaseTics());
- String GMTtime = stamp.toGMTString().substring(0, 19);
- long fracSec = stamp.getNanos() / 1000000; // divide by a million
- String fracSecStr = String.format("%03d", fracSec);
- infoBlock.append("<utc>" + GMTtime + "." + fracSecStr + "</utc>");
-
- infoBlock.append(TraceDeviceInfo.getLogHeaderBluetoothPairs());
- infoBlock.append(getSmartDeviceLinkTraceRoot(dumpReason, seqNo));
-
- write.append(infoBlock);
-
- write.append("</info>" + "<msgs>");
- return write.toString();
- } // end-method
-
- private static String getSmartDeviceLinkTraceRoot(String dumpReason, int seqNo) {
- StringBuilder write = new StringBuilder("<SmartDeviceLinktraceroot>" + "<sequencenum>" + seqNo
- + "</sequencenum>" + "<dumpreason>" + dumpReason
- + "</dumpreason><tracelevel>");
-
- write.append("<tran>" + DiagLevel.getLevel(Mod.tran) + "</tran>");
- write.append("<proto>" + DiagLevel.getLevel(Mod.proto) + "</proto>");
- write.append("<mar>" + DiagLevel.getLevel(Mod.mar) + "</mar>");
- write.append("<rpc>" + DiagLevel.getLevel(Mod.rpc) + "</rpc>");
- write.append("<proxy>" + DiagLevel.getLevel(Mod.proxy) + "</proxy>");
- write.append("<app>" + DiagLevel.getLevel(Mod.app) + "</app>");
-
- write.append("</tracelevel>");
- write.append("</SmartDeviceLinktraceroot>");
- return write.toString();
- } // end-method
-} // end-class
+package com.smartdevicelink.trace;\r
+\r
+import java.sql.Timestamp;\r
+\r
+import android.bluetooth.BluetoothDevice;\r
+import android.os.Build;\r
+import android.os.Debug;\r
+import android.os.Process;\r
+\r
+import com.smartdevicelink.protocol.ProtocolFrameHeader;\r
+import com.smartdevicelink.protocol.enums.FrameDataControlFrameType;\r
+import com.smartdevicelink.protocol.enums.FrameType;\r
+import com.smartdevicelink.protocol.enums.SessionType;\r
+import com.smartdevicelink.proxy.RPCMessage;\r
+import com.smartdevicelink.proxy.RPCRequest;\r
+import com.smartdevicelink.proxy.RPCResponse;\r
+import com.smartdevicelink.trace.enums.DetailLevel;\r
+import com.smartdevicelink.trace.enums.InterfaceActivityDirection;\r
+import com.smartdevicelink.trace.enums.Mod;\r
+import com.smartdevicelink.transport.SiphonServer;\r
+import com.smartdevicelink.util.BitConverter;\r
+import com.smartdevicelink.util.DebugTool;\r
+import com.smartdevicelink.util.NativeLogTool;\r
+\r
+/* This class handles the global TraceSettings as requested by the users either through the combination of the following\r
+ 1. System defaults\r
+ 2. Application XML config\r
+ 3. Programmatic requests from application itself\r
+\r
+ It is manifested in the <applink>...</applink> tags\r
+ */\r
+\r
+public class SmartDeviceLinkTrace {\r
+ private static final String SMARTDEVICELINK_LIB_TRACE_KEY = "42baba60-eb57-11df-98cf-0800200c9a66";\r
+ \r
+ static boolean canWriteLogs = false;\r
+ \r
+ public static final String SYSTEM_LOG_TAG = "SmartDeviceLinkTrace";\r
+ \r
+ private static long baseTics = java.lang.System.currentTimeMillis();\r
+ private final static String KeyStr = SMARTDEVICELINK_LIB_TRACE_KEY;\r
+ private static boolean acceptAPITraceAdjustments = true;\r
+\r
+ protected static ISTListener m_appTraceListener = null;\r
+\r
+ ///\r
+ /// The PUBLIC interface to SmartDeviceLinkTrace starts here\r
+ ///\r
+\r
+\r
+ public static void setAcceptAPITraceAdjustments(Boolean APITraceAdjustmentsAccepted) {\r
+ if (APITraceAdjustmentsAccepted != null) {\r
+ acceptAPITraceAdjustments = APITraceAdjustmentsAccepted;\r
+ }\r
+ }\r
+ \r
+ public static boolean getAcceptAPITraceAdjustments() {\r
+ return acceptAPITraceAdjustments;\r
+ }\r
+ \r
+ public static void setAppTraceListener(ISTListener listener) {\r
+ m_appTraceListener = listener;\r
+ } // end-method\r
+\r
+ public static void setTracingEnable(Boolean enable) {\r
+ if (enable != null) {\r
+ canWriteLogs = enable;\r
+ }\r
+ } // end-method\r
+\r
+ public static void setAppTraceLevel(DetailLevel dt) {\r
+ if ( dt != null && acceptAPITraceAdjustments)\r
+ DiagLevel.setLevel(Mod.app, dt);\r
+ } // end-method\r
+\r
+ public static void setProxyTraceLevel(DetailLevel dt) {\r
+ if (dt != null && acceptAPITraceAdjustments)\r
+ DiagLevel.setLevel(Mod.proxy, dt);\r
+ } // end-method\r
+\r
+ public static void setRpcTraceLevel(DetailLevel dt) {\r
+ if (dt != null && acceptAPITraceAdjustments)\r
+ DiagLevel.setLevel(Mod.rpc, dt);\r
+ } // end-method\r
+\r
+ public static void setMarshallingTraceLevel(DetailLevel dt) {\r
+ if (dt != null && acceptAPITraceAdjustments)\r
+ DiagLevel.setLevel(Mod.mar, dt);\r
+ } // end-method\r
+\r
+ public static void setProtocolTraceLevel(DetailLevel dt) {\r
+ if (dt != null && acceptAPITraceAdjustments)\r
+ DiagLevel.setLevel(Mod.proto, dt);\r
+ } // end-method\r
+\r
+ public static void setTransportTraceLevel(DetailLevel dt) {\r
+ if (dt != null && acceptAPITraceAdjustments)\r
+ DiagLevel.setLevel(Mod.tran, dt);\r
+ } // end-method\r
+\r
+ private static String encodeTraceMessage(long timestamp, Mod module, InterfaceActivityDirection msgDirection, String msgBodyXml) {\r
+ StringBuilder sb = new StringBuilder("<msg><dms>");\r
+ sb.append(timestamp);\r
+ sb.append("</dms><pid>");\r
+ sb.append(Process.myPid());\r
+ sb.append("</pid><tid>");\r
+ sb.append(Thread.currentThread().getId());\r
+ sb.append("</tid><mod>");\r
+ sb.append(module.toString());\r
+ sb.append("</mod>");\r
+ if (msgDirection != InterfaceActivityDirection.None) {\r
+ sb.append("<dir>");\r
+ sb.append(interfaceActivityDirectionToString(msgDirection));\r
+ sb.append("</dir>");\r
+ } // end-if\r
+ sb.append(msgBodyXml);\r
+ sb.append("</msg>");\r
+\r
+ return sb.toString();\r
+ } // end-method\r
+\r
+ private static String interfaceActivityDirectionToString(InterfaceActivityDirection iaDirection) {\r
+ String str = "";\r
+ switch (iaDirection) {\r
+ case Receive:\r
+ str = "rx";\r
+ break;\r
+ case Transmit:\r
+ str = "tx";\r
+ break;\r
+ } // end-switch\r
+ return str;\r
+ } // end-method\r
+\r
+ static String B64EncodeForXML(String data) {\r
+ return Mime.base64Encode(data);\r
+ // Base64 only available in 2.2, when SmartDeviceLink base is 2.2 use: return Base64.encodeToString(data.getBytes(), Base64.DEFAULT);\r
+ } // end-method\r
+ \r
+ public static void logProxyEvent(String eventText, String token) {\r
+ if (DiagLevel.getLevel(Mod.proxy) == DetailLevel.OFF || !token.equals(KeyStr)) {\r
+ return;\r
+ } // end-if\r
+\r
+ String msg = SmartDeviceLinkTrace.B64EncodeForXML(eventText);\r
+ String xml = SmartDeviceLinkTrace.encodeTraceMessage(SmartDeviceLinkTrace.getBaseTicsDelta(), Mod.proxy, InterfaceActivityDirection.None, "<d>" + msg + "</d>");\r
+ writeXmlTraceMessage(xml);\r
+ } // end-method\r
+\r
+ public static void logAppEvent(String eventText) {\r
+ if (DiagLevel.getLevel(Mod.app) == DetailLevel.OFF) {\r
+ return;\r
+ } // end-if\r
+\r
+ long timestamp = SmartDeviceLinkTrace.getBaseTicsDelta();\r
+ String msg = SmartDeviceLinkTrace.B64EncodeForXML(eventText);\r
+ String xml = SmartDeviceLinkTrace.encodeTraceMessage(timestamp, Mod.app, InterfaceActivityDirection.None, "<d>" + msg + "</d>");\r
+ writeXmlTraceMessage(xml);\r
+ } // end-method\r
+\r
+ public static void logRPCEvent(InterfaceActivityDirection msgDirection, RPCMessage rpcMsg, String token) {\r
+ DetailLevel dl = DiagLevel.getLevel(Mod.rpc);\r
+ if (dl == DetailLevel.OFF || !token.equals(KeyStr)) {\r
+ return;\r
+ } // end-if\r
+\r
+ long timestamp = SmartDeviceLinkTrace.getBaseTicsDelta();\r
+ String xml = SmartDeviceLinkTrace.encodeTraceMessage(timestamp, Mod.rpc, msgDirection, rpc2Xml(dl, rpcMsg));\r
+ writeXmlTraceMessage(xml);\r
+ } // end-method\r
+\r
+ private static String rpc2Xml(DetailLevel dl, RPCMessage rpcMsg) {\r
+ StringBuilder rpcAsXml = new StringBuilder();\r
+ rpcAsXml.append("<op>");\r
+ rpcAsXml.append(rpcMsg.getFunctionName());\r
+ rpcAsXml.append("</op>");\r
+ boolean hasCorrelationID = false;\r
+ Integer correlationID = -1;\r
+ if (rpcMsg instanceof RPCRequest) {\r
+ hasCorrelationID = true;\r
+ correlationID = ((RPCRequest)rpcMsg).getCorrelationID();\r
+ } else if (rpcMsg instanceof RPCResponse) {\r
+ hasCorrelationID = true;\r
+ correlationID = ((RPCResponse)rpcMsg).getCorrelationID();\r
+ } // end-if\r
+ if (hasCorrelationID) {\r
+ rpcAsXml.append("<cid>");\r
+ rpcAsXml.append(correlationID);\r
+ rpcAsXml.append("</cid>");\r
+ } // end-if\r
+ rpcAsXml.append("<type>");\r
+ rpcAsXml.append(rpcMsg.getMessageType());\r
+ rpcAsXml.append("</type>");\r
+ //rpcAsXml.append(newline);\r
+\r
+ if (dl == DetailLevel.VERBOSE) {\r
+ OpenRPCMessage orpcmsg = new OpenRPCMessage(rpcMsg);\r
+ String rpcParamList = orpcmsg.msgDump();\r
+ String msg = SmartDeviceLinkTrace.B64EncodeForXML(rpcParamList);\r
+ rpcAsXml.append("<d>");\r
+ rpcAsXml.append(msg);\r
+ rpcAsXml.append("</d>");\r
+ } // end-if\r
+ return rpcAsXml.toString();\r
+ } // end-method\r
+\r
+ public static void logMarshallingEvent(InterfaceActivityDirection msgDirection, byte[] marshalledMessage, String token) {\r
+ DetailLevel dl = DiagLevel.getLevel(Mod.mar);\r
+ if (dl == DetailLevel.OFF || !token.equals(KeyStr)) {\r
+ return;\r
+ } // end-fif\r
+\r
+ long timestamp = SmartDeviceLinkTrace.getBaseTicsDelta();\r
+ StringBuilder msg = new StringBuilder();\r
+ msg.append("<sz>");\r
+ msg.append(marshalledMessage.length);\r
+ msg.append("</sz>");\r
+ if (dl == DetailLevel.VERBOSE) {\r
+ msg.append("<d>");\r
+ msg.append(Mime.base64Encode(marshalledMessage));\r
+ // Base64 only available in 2.2, when SmartDeviceLink base is 2.2 use: msg.append(Base64.encodeToString(marshalledMessage, Base64.DEFAULT));\r
+ msg.append("</d>");\r
+ } // end-if\r
+ String xml = SmartDeviceLinkTrace.encodeTraceMessage(timestamp, Mod.mar, msgDirection, msg.toString());\r
+ writeXmlTraceMessage(xml);\r
+ } // end-method\r
+\r
+ public static void logProtocolEvent(InterfaceActivityDirection frameDirection, ProtocolFrameHeader frameHeader, byte[] frameData, int frameDataOffset, int frameDataLength, String token) {\r
+ DetailLevel dl = DiagLevel.getLevel(Mod.proto);\r
+ if (dl == DetailLevel.OFF || !token.equals(KeyStr)) {\r
+ return;\r
+ } // end-if\r
+\r
+ StringBuffer protoMsg = new StringBuffer();\r
+ protoMsg.append("<frame>");\r
+ protoMsg.append(SmartDeviceLinkTrace.getProtocolFrameHeaderInfo(frameHeader, frameData));\r
+ if (dl == DetailLevel.VERBOSE) {\r
+ if (frameData != null && frameDataLength > 0) {\r
+ protoMsg.append("<d>");\r
+ String bytesInfo = "";\r
+ bytesInfo = Mime.base64Encode(frameData, frameDataOffset, frameDataLength);\r
+ // Base64 only available in 2.2, when SmartDeviceLink base is 2.2 use: bytesInfo = Base64.encodeToString(frameData, frameDataOffset, frameDataLength, Base64.DEFAULT);\r
+ protoMsg.append(bytesInfo);\r
+ protoMsg.append("</d>");\r
+ } // end-if\r
+ } // end-if\r
+ protoMsg.append("</frame>");\r
+ String xml = SmartDeviceLinkTrace.encodeTraceMessage(SmartDeviceLinkTrace.getBaseTicsDelta(), Mod.proto, frameDirection, protoMsg.toString());\r
+ writeXmlTraceMessage(xml);\r
+ } // end-method\r
+\r
+ private static String getProtocolFrameType(FrameType f) {\r
+ if (f == FrameType.Control)\r
+ return "Control";\r
+ else if (f == FrameType.Consecutive)\r
+ return "Consecutive";\r
+ else if (f == FrameType.First)\r
+ return "First";\r
+ else if (f == FrameType.Single)\r
+ return "Single";\r
+\r
+ return "Unknown";\r
+ } // end-method\r
+\r
+ private static String getProtocolSessionType(SessionType serviceType) {\r
+ String s;\r
+ if (serviceType == SessionType.RPC )\r
+ s = "rpc";\r
+ else if (serviceType == SessionType.Bulk_Data)\r
+ s = "bulk";\r
+ else\r
+ s = "Unknown";\r
+ return s;\r
+ } // end-method\r
+\r
+ private static String getProtocolFrameHeaderInfo(ProtocolFrameHeader hdr, byte[] buf) {\r
+ StringBuilder sb = new StringBuilder();\r
+ sb.append("<hdr>");\r
+ sb.append("<ver>");\r
+ sb.append(hdr.getVersion());\r
+ sb.append("</ver><cmp>");\r
+ sb.append(hdr.isCompressed());\r
+ sb.append("</cmp><ft>");\r
+ sb.append(getProtocolFrameType(hdr.getFrameType()));\r
+ sb.append("</ft><st>");\r
+ sb.append(getProtocolSessionType(hdr.getSessionType()));\r
+ sb.append("</st><sid>");\r
+ sb.append(hdr.getSessionID());\r
+ sb.append("</sid><sz>");\r
+ sb.append(hdr.getDataSize());\r
+ sb.append("</sz>");\r
+\r
+ int frameData = hdr.getFrameData();\r
+ if (hdr.getFrameType() == FrameType.Control) {\r
+ sb.append("<ca>");\r
+ if (frameData == FrameDataControlFrameType.StartSession.getValue()) \r
+ sb.append("StartSession");\r
+ else if (frameData == FrameDataControlFrameType.StartSessionACK.getValue())\r
+ sb.append("StartSessionACK");\r
+ else if (frameData == FrameDataControlFrameType.StartSessionNACK.getValue())\r
+ sb.append("StartSessionNACK");\r
+ else if (frameData == FrameDataControlFrameType.EndSession.getValue())\r
+ sb.append("EndSession");\r
+ sb.append("</ca>");\r
+ } else if (hdr.getFrameType() == FrameType.Consecutive ) {\r
+ sb.append("<fsn>");\r
+ if (frameData == 0 )\r
+ sb.append("lastFrame");\r
+ else\r
+ sb.append(String.format("%02X",frameData)); \r
+ sb.append("</fsn>");\r
+ } else if (hdr.getFrameType() == FrameType.First ) {\r
+ int totalSize = BitConverter.intFromByteArray(buf, 0); \r
+ int numFrames = BitConverter.intFromByteArray(buf, 4);\r
+ sb.append("<total>" + totalSize + "</total><numframes>" + numFrames + "</numframes>");\r
+ } else if (hdr.getFrameType() == FrameType.Single ) {\r
+ sb.append("<single/>");\r
+ }\r
+\r
+ sb.append("</hdr>");\r
+\r
+ return sb.toString();\r
+ } // end-method\r
+\r
+ public static String getBTDeviceInfo(BluetoothDevice btDevice) {\r
+ StringBuilder sb = new StringBuilder();\r
+ sb.append("<btp>");\r
+ String btdn = btDevice.getName();\r
+ sb.append("<btn>");\r
+ sb.append(SmartDeviceLinkTrace.B64EncodeForXML(btdn));\r
+ sb.append("</btn>");\r
+ sb.append("<bta>" + btDevice.getAddress() + "</bta>");\r
+ sb.append("<bts>" + btDevice.getBondState() + "</bts>");\r
+ sb.append("</btp>");\r
+ return sb.toString();\r
+ } // end-method\r
+\r
+ public static void logTransportEvent(String preamble, String transportSpecificInfoXml, InterfaceActivityDirection msgDirection, byte buf[], int byteLength, String token) {\r
+ logTransportEvent(preamble, transportSpecificInfoXml, msgDirection, buf, 0, byteLength, token);\r
+ } // end-method\r
+\r
+ private static void checkB64(String x, byte[] buf, int offset, int byteLength) {\r
+ if ((x.length() % 4) != 0) {\r
+ 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
+ } // end-if\r
+ } // end-method\r
+\r
+ public static void logTransportEvent(String preamble, String transportSpecificInfoXml, InterfaceActivityDirection msgDirection, byte buf[], int offset, int byteLength, String token) {\r
+ if (DiagLevel.getLevel(Mod.tran) == DetailLevel.OFF || !token.equals(KeyStr)) {\r
+ return;\r
+ } // end-if\r
+\r
+ StringBuilder msg = new StringBuilder();\r
+ if (transportSpecificInfoXml != null && transportSpecificInfoXml.length() > 0) {\r
+ msg.append(transportSpecificInfoXml);\r
+ } // end-if\r
+ if (preamble != null && preamble.length() > 0) {\r
+ msg.append("<desc>");\r
+ msg.append(preamble);\r
+ msg.append("</desc>");\r
+ } // end-if\r
+ if (buf != null) {\r
+ msg.append("<sz>");\r
+ msg.append(byteLength);\r
+ msg.append("</sz>");\r
+ DetailLevel dl = DiagLevel.getLevel(Mod.tran);\r
+ if (dl == DetailLevel.VERBOSE) {\r
+ if (buf != null && byteLength > 0) {\r
+ msg.append("<d>");\r
+ String bytesInfo = Mime.base64Encode(buf, offset, byteLength);\r
+ checkB64(bytesInfo, buf, offset, byteLength);\r
+ msg.append(bytesInfo);\r
+ msg.append("</d>");\r
+ } // end-if\r
+ } // end-if\r
+ } // end-if\r
+ String xml = SmartDeviceLinkTrace.encodeTraceMessage(SmartDeviceLinkTrace.getBaseTicsDelta(), Mod.tran, msgDirection, msg.toString());\r
+ writeXmlTraceMessage(xml);\r
+ } // end-method\r
+\r
+ // Package-scoped\r
+ static long getBaseTicsDelta() {\r
+ return java.lang.System.currentTimeMillis() - getBaseTics();\r
+ }\r
+\r
+ // Package-scoped\r
+ static long getBaseTics() {\r
+ return baseTics;\r
+ } // end-method\r
+\r
+ public static Boolean writeMessageToSiphonServer(String info) {\r
+ return SiphonServer.sendFormattedTraceMessage(info);\r
+ }\r
+\r
+ private static void writeXmlTraceMessage(String msg) {\r
+ try { \r
+ // Attempt to write formatted message to the Siphon\r
+ if (false == writeMessageToSiphonServer(msg)) {\r
+ // If writing to the Siphon fails, write to the native log\r
+ NativeLogTool.logInfo(SmartDeviceLinkTrace.SYSTEM_LOG_TAG, msg);\r
+ }\r
+ \r
+ ISTListener localTraceListener = m_appTraceListener;\r
+\r
+ if (localTraceListener != null) {\r
+ try {\r
+ localTraceListener.logXmlMsg(msg, KeyStr);\r
+ } catch (Exception ex) {\r
+ DebugTool.logError("Failure calling ISTListener: " + ex.toString(), ex);\r
+ } // end-catch\r
+ } // end-if\r
+ } catch (Exception ex) {\r
+ NativeLogTool.logError(SmartDeviceLinkTrace.SYSTEM_LOG_TAG, "Failure writing XML trace message: " + ex.toString());\r
+ }\r
+ } // end-method\r
+ \r
+ // Package-scoped\r
+ public static String getLogHeader(String dumpReason, int seqNo) {\r
+ final String Sep = "-";\r
+ StringBuilder write = new StringBuilder("<?xml version=\"1.0\"?>" + "<logs>");\r
+ write.append("<info>");\r
+ StringBuilder infoBlock = new StringBuilder();\r
+ String hostInfo = Build.BRAND + Sep + Build.MANUFACTURER + Sep + Build.MODEL + "(" + Build.HOST + ")";\r
+ infoBlock.append("<host>" + SmartDeviceLinkTrace.B64EncodeForXML(hostInfo) + "</host>");\r
+ String osv = Build.VERSION.RELEASE + " (" + Build.VERSION.CODENAME + ")";\r
+ infoBlock.append("<osv>" + SmartDeviceLinkTrace.B64EncodeForXML(osv) + "</osv>");\r
+ infoBlock.append(TraceDeviceInfo.getTelephonyHeader());\r
+\r
+ long heapSize = Debug.getNativeHeapFreeSize() / 1024;\r
+ long heapAllocated = Debug.getNativeHeapAllocatedSize() / 1024;\r
+ infoBlock.append("<mem><hf>" + heapSize + "KB</hf><ha>" + heapAllocated + "KB</ha></mem>");\r
+ infoBlock.append("<np>" + Runtime.getRuntime().availableProcessors() + "</np>");\r
+ infoBlock.append("<pid>" + Process.myPid() + "</pid>");\r
+ infoBlock.append("<tid>" + Thread.currentThread().getId() + "</tid>");\r
+\r
+ // String dateStamp = (String)\r
+ // DateFormat.format("yy-MM-dd hh:mm:ss SSS", new Timestamp(baseTics));\r
+ Timestamp stamp = new Timestamp(SmartDeviceLinkTrace.getBaseTics());\r
+ String GMTtime = stamp.toGMTString().substring(0, 19);\r
+ long fracSec = stamp.getNanos() / 1000000; // divide by a million\r
+ String fracSecStr = String.format("%03d", fracSec);\r
+ infoBlock.append("<utc>" + GMTtime + "." + fracSecStr + "</utc>");\r
+\r
+ infoBlock.append(TraceDeviceInfo.getLogHeaderBluetoothPairs());\r
+ infoBlock.append(getApplinkTraceRoot(dumpReason, seqNo));\r
+\r
+ write.append(infoBlock);\r
+\r
+ write.append("</info>" + "<msgs>");\r
+ return write.toString();\r
+ } // end-method\r
+ \r
+ private static String getApplinkTraceRoot(String dumpReason, int seqNo) {\r
+ StringBuilder write = new StringBuilder("<applinktraceroot>" + "<sequencenum>" + seqNo\r
+ + "</sequencenum>" + "<dumpreason>" + dumpReason\r
+ + "</dumpreason><tracelevel>");\r
+\r
+ write.append("<tran>" + DiagLevel.getLevel(Mod.tran) + "</tran>");\r
+ write.append("<proto>" + DiagLevel.getLevel(Mod.proto) + "</proto>");\r
+ write.append("<mar>" + DiagLevel.getLevel(Mod.mar) + "</mar>");\r
+ write.append("<rpc>" + DiagLevel.getLevel(Mod.rpc) + "</rpc>");\r
+ write.append("<proxy>" + DiagLevel.getLevel(Mod.proxy) + "</proxy>");\r
+ write.append("<app>" + DiagLevel.getLevel(Mod.app) + "</app>");\r
+\r
+ write.append("</tracelevel>");\r
+ write.append("</applinktraceroot>");\r
+ return write.toString();\r
+ } // end-method\r
+} // end-class
\ No newline at end of file