Switch to using android.telecom.Log in Telecom

Sorry.
CP from: https://android-review.googlesource.com/#/c/287332/

Test: Added unit tests for Log Sessions and Events. All other affected
unit tests still pass.
Bug: 26571395
Change-Id: I890d68d935cd554ba89042e99c155757697e1a37
diff --git a/proguard.flags b/proguard.flags
index 357336b..4e0c310 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -3,6 +3,6 @@
 -keep class com.android.server.telecom.TelecomSystem {
   *;
 }
--keep class com.android.server.telecom.Log {
+-keep class android.telecom.Log {
   *;
 }
diff --git a/src/com/android/server/telecom/Analytics.java b/src/com/android/server/telecom/Analytics.java
index 4456734..59c8a9d 100644
--- a/src/com/android/server/telecom/Analytics.java
+++ b/src/com/android/server/telecom/Analytics.java
@@ -18,9 +18,11 @@
 
 import android.telecom.Connection;
 import android.telecom.DisconnectCause;
+import android.telecom.Logging.EventManager;
 import android.telecom.ParcelableCallAnalytics;
 import android.telecom.TelecomAnalytics;
 import android.util.Base64;
+import android.telecom.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
@@ -48,92 +50,94 @@
 
     public static final Map<String, Integer> sLogEventToAnalyticsEvent =
             new HashMap<String, Integer>() {{
-                put(Log.Events.SET_SELECT_PHONE_ACCOUNT, AnalyticsEvent.SET_SELECT_PHONE_ACCOUNT);
-                put(Log.Events.REQUEST_HOLD, AnalyticsEvent.REQUEST_HOLD);
-                put(Log.Events.REQUEST_UNHOLD, AnalyticsEvent.REQUEST_UNHOLD);
-                put(Log.Events.SWAP, AnalyticsEvent.SWAP);
-                put(Log.Events.SKIP_RINGING, AnalyticsEvent.SKIP_RINGING);
-                put(Log.Events.CONFERENCE_WITH, AnalyticsEvent.CONFERENCE_WITH);
-                put(Log.Events.SPLIT_FROM_CONFERENCE, AnalyticsEvent.SPLIT_CONFERENCE);
-                put(Log.Events.SET_PARENT, AnalyticsEvent.SET_PARENT);
-                put(Log.Events.MUTE, AnalyticsEvent.MUTE);
-                put(Log.Events.UNMUTE, AnalyticsEvent.UNMUTE);
-                put(Log.Events.AUDIO_ROUTE_BT, AnalyticsEvent.AUDIO_ROUTE_BT);
-                put(Log.Events.AUDIO_ROUTE_EARPIECE, AnalyticsEvent.AUDIO_ROUTE_EARPIECE);
-                put(Log.Events.AUDIO_ROUTE_HEADSET, AnalyticsEvent.AUDIO_ROUTE_HEADSET);
-                put(Log.Events.AUDIO_ROUTE_SPEAKER, AnalyticsEvent.AUDIO_ROUTE_SPEAKER);
-                put(Log.Events.SILENCE, AnalyticsEvent.SILENCE);
-                put(Log.Events.SCREENING_COMPLETED, AnalyticsEvent.SCREENING_COMPLETED);
-                put(Log.Events.BLOCK_CHECK_FINISHED, AnalyticsEvent.BLOCK_CHECK_FINISHED);
-                put(Log.Events.DIRECT_TO_VM_FINISHED, AnalyticsEvent.DIRECT_TO_VM_FINISHED);
-                put(Log.Events.REMOTELY_HELD, AnalyticsEvent.REMOTELY_HELD);
-                put(Log.Events.REMOTELY_UNHELD, AnalyticsEvent.REMOTELY_UNHELD);
-                put(Log.Events.REQUEST_PULL, AnalyticsEvent.REQUEST_PULL);
-                put(Log.Events.REQUEST_ACCEPT, AnalyticsEvent.REQUEST_ACCEPT);
-                put(Log.Events.REQUEST_REJECT, AnalyticsEvent.REQUEST_REJECT);
-                put(Log.Events.SET_ACTIVE, AnalyticsEvent.SET_ACTIVE);
-                put(Log.Events.SET_DISCONNECTED, AnalyticsEvent.SET_DISCONNECTED);
-                put(Log.Events.SET_HOLD, AnalyticsEvent.SET_HOLD);
-                put(Log.Events.SET_DIALING, AnalyticsEvent.SET_DIALING);
-                put(Log.Events.START_CONNECTION, AnalyticsEvent.START_CONNECTION);
-                put(Log.Events.BIND_CS, AnalyticsEvent.BIND_CS);
-                put(Log.Events.CS_BOUND, AnalyticsEvent.CS_BOUND);
-                put(Log.Events.SCREENING_SENT, AnalyticsEvent.SCREENING_SENT);
-                put(Log.Events.DIRECT_TO_VM_INITIATED, AnalyticsEvent.DIRECT_TO_VM_INITIATED);
-                put(Log.Events.BLOCK_CHECK_INITIATED, AnalyticsEvent.BLOCK_CHECK_INITIATED);
-                put(Log.Events.FILTERING_INITIATED, AnalyticsEvent.FILTERING_INITIATED);
-                put(Log.Events.FILTERING_COMPLETED, AnalyticsEvent.FILTERING_COMPLETED);
-                put(Log.Events.FILTERING_TIMED_OUT, AnalyticsEvent.FILTERING_TIMED_OUT);
+                put(LogUtils.Events.SET_SELECT_PHONE_ACCOUNT,
+                        AnalyticsEvent.SET_SELECT_PHONE_ACCOUNT);
+                put(LogUtils.Events.REQUEST_HOLD, AnalyticsEvent.REQUEST_HOLD);
+                put(LogUtils.Events.REQUEST_UNHOLD, AnalyticsEvent.REQUEST_UNHOLD);
+                put(LogUtils.Events.SWAP, AnalyticsEvent.SWAP);
+                put(LogUtils.Events.SKIP_RINGING, AnalyticsEvent.SKIP_RINGING);
+                put(LogUtils.Events.CONFERENCE_WITH, AnalyticsEvent.CONFERENCE_WITH);
+                put(LogUtils.Events.SPLIT_FROM_CONFERENCE, AnalyticsEvent.SPLIT_CONFERENCE);
+                put(LogUtils.Events.SET_PARENT, AnalyticsEvent.SET_PARENT);
+                put(LogUtils.Events.MUTE, AnalyticsEvent.MUTE);
+                put(LogUtils.Events.UNMUTE, AnalyticsEvent.UNMUTE);
+                put(LogUtils.Events.AUDIO_ROUTE_BT, AnalyticsEvent.AUDIO_ROUTE_BT);
+                put(LogUtils.Events.AUDIO_ROUTE_EARPIECE, AnalyticsEvent.AUDIO_ROUTE_EARPIECE);
+                put(LogUtils.Events.AUDIO_ROUTE_HEADSET, AnalyticsEvent.AUDIO_ROUTE_HEADSET);
+                put(LogUtils.Events.AUDIO_ROUTE_SPEAKER, AnalyticsEvent.AUDIO_ROUTE_SPEAKER);
+                put(LogUtils.Events.SILENCE, AnalyticsEvent.SILENCE);
+                put(LogUtils.Events.SCREENING_COMPLETED, AnalyticsEvent.SCREENING_COMPLETED);
+                put(LogUtils.Events.BLOCK_CHECK_FINISHED, AnalyticsEvent.BLOCK_CHECK_FINISHED);
+                put(LogUtils.Events.DIRECT_TO_VM_FINISHED, AnalyticsEvent.DIRECT_TO_VM_FINISHED);
+                put(LogUtils.Events.REMOTELY_HELD, AnalyticsEvent.REMOTELY_HELD);
+                put(LogUtils.Events.REMOTELY_UNHELD, AnalyticsEvent.REMOTELY_UNHELD);
+                put(LogUtils.Events.REQUEST_PULL, AnalyticsEvent.REQUEST_PULL);
+                put(LogUtils.Events.REQUEST_ACCEPT, AnalyticsEvent.REQUEST_ACCEPT);
+                put(LogUtils.Events.REQUEST_REJECT, AnalyticsEvent.REQUEST_REJECT);
+                put(LogUtils.Events.SET_ACTIVE, AnalyticsEvent.SET_ACTIVE);
+                put(LogUtils.Events.SET_DISCONNECTED, AnalyticsEvent.SET_DISCONNECTED);
+                put(LogUtils.Events.SET_HOLD, AnalyticsEvent.SET_HOLD);
+                put(LogUtils.Events.SET_DIALING, AnalyticsEvent.SET_DIALING);
+                put(LogUtils.Events.START_CONNECTION, AnalyticsEvent.START_CONNECTION);
+                put(LogUtils.Events.BIND_CS, AnalyticsEvent.BIND_CS);
+                put(LogUtils.Events.CS_BOUND, AnalyticsEvent.CS_BOUND);
+                put(LogUtils.Events.SCREENING_SENT, AnalyticsEvent.SCREENING_SENT);
+                put(LogUtils.Events.DIRECT_TO_VM_INITIATED, AnalyticsEvent.DIRECT_TO_VM_INITIATED);
+                put(LogUtils.Events.BLOCK_CHECK_INITIATED, AnalyticsEvent.BLOCK_CHECK_INITIATED);
+                put(LogUtils.Events.FILTERING_INITIATED, AnalyticsEvent.FILTERING_INITIATED);
+                put(LogUtils.Events.FILTERING_COMPLETED, AnalyticsEvent.FILTERING_COMPLETED);
+                put(LogUtils.Events.FILTERING_TIMED_OUT, AnalyticsEvent.FILTERING_TIMED_OUT);
             }};
 
     public static final Map<String, Integer> sLogSessionToSessionId =
             new HashMap<String, Integer> () {{
-                put(Log.Sessions.ICA_ANSWER_CALL, SessionTiming.ICA_ANSWER_CALL);
-                put(Log.Sessions.ICA_REJECT_CALL, SessionTiming.ICA_REJECT_CALL);
-                put(Log.Sessions.ICA_DISCONNECT_CALL, SessionTiming.ICA_DISCONNECT_CALL);
-                put(Log.Sessions.ICA_HOLD_CALL, SessionTiming.ICA_HOLD_CALL);
-                put(Log.Sessions.ICA_UNHOLD_CALL, SessionTiming.ICA_UNHOLD_CALL);
-                put(Log.Sessions.ICA_MUTE, SessionTiming.ICA_MUTE);
-                put(Log.Sessions.ICA_SET_AUDIO_ROUTE, SessionTiming.ICA_SET_AUDIO_ROUTE);
-                put(Log.Sessions.ICA_CONFERENCE, SessionTiming.ICA_CONFERENCE);
-                put(Log.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE,
+                put(LogUtils.Sessions.ICA_ANSWER_CALL, SessionTiming.ICA_ANSWER_CALL);
+                put(LogUtils.Sessions.ICA_REJECT_CALL, SessionTiming.ICA_REJECT_CALL);
+                put(LogUtils.Sessions.ICA_DISCONNECT_CALL, SessionTiming.ICA_DISCONNECT_CALL);
+                put(LogUtils.Sessions.ICA_HOLD_CALL, SessionTiming.ICA_HOLD_CALL);
+                put(LogUtils.Sessions.ICA_UNHOLD_CALL, SessionTiming.ICA_UNHOLD_CALL);
+                put(LogUtils.Sessions.ICA_MUTE, SessionTiming.ICA_MUTE);
+                put(LogUtils.Sessions.ICA_SET_AUDIO_ROUTE, SessionTiming.ICA_SET_AUDIO_ROUTE);
+                put(LogUtils.Sessions.ICA_CONFERENCE, SessionTiming.ICA_CONFERENCE);
+                put(LogUtils.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE,
                         SessionTiming.CSW_HANDLE_CREATE_CONNECTION_COMPLETE);
-                put(Log.Sessions.CSW_SET_ACTIVE, SessionTiming.CSW_SET_ACTIVE);
-                put(Log.Sessions.CSW_SET_RINGING, SessionTiming.CSW_SET_RINGING);
-                put(Log.Sessions.CSW_SET_DIALING, SessionTiming.CSW_SET_DIALING);
-                put(Log.Sessions.CSW_SET_DISCONNECTED, SessionTiming.CSW_SET_DISCONNECTED);
-                put(Log.Sessions.CSW_SET_ON_HOLD, SessionTiming.CSW_SET_ON_HOLD);
-                put(Log.Sessions.CSW_REMOVE_CALL, SessionTiming.CSW_REMOVE_CALL);
-                put(Log.Sessions.CSW_SET_IS_CONFERENCED, SessionTiming.CSW_SET_IS_CONFERENCED);
-                put(Log.Sessions.CSW_ADD_CONFERENCE_CALL, SessionTiming.CSW_ADD_CONFERENCE_CALL);
+                put(LogUtils.Sessions.CSW_SET_ACTIVE, SessionTiming.CSW_SET_ACTIVE);
+                put(LogUtils.Sessions.CSW_SET_RINGING, SessionTiming.CSW_SET_RINGING);
+                put(LogUtils.Sessions.CSW_SET_DIALING, SessionTiming.CSW_SET_DIALING);
+                put(LogUtils.Sessions.CSW_SET_DISCONNECTED, SessionTiming.CSW_SET_DISCONNECTED);
+                put(LogUtils.Sessions.CSW_SET_ON_HOLD, SessionTiming.CSW_SET_ON_HOLD);
+                put(LogUtils.Sessions.CSW_REMOVE_CALL, SessionTiming.CSW_REMOVE_CALL);
+                put(LogUtils.Sessions.CSW_SET_IS_CONFERENCED, SessionTiming.CSW_SET_IS_CONFERENCED);
+                put(LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL,
+                        SessionTiming.CSW_ADD_CONFERENCE_CALL);
 
             }};
 
     public static final Map<String, Integer> sLogEventTimingToAnalyticsEventTiming =
             new HashMap<String, Integer>() {{
-                put(Log.Events.Timings.ACCEPT_TIMING,
+                put(LogUtils.Events.Timings.ACCEPT_TIMING,
                         ParcelableCallAnalytics.EventTiming.ACCEPT_TIMING);
-                put(Log.Events.Timings.REJECT_TIMING,
+                put(LogUtils.Events.Timings.REJECT_TIMING,
                         ParcelableCallAnalytics.EventTiming.REJECT_TIMING);
-                put(Log.Events.Timings.DISCONNECT_TIMING,
+                put(LogUtils.Events.Timings.DISCONNECT_TIMING,
                         ParcelableCallAnalytics.EventTiming.DISCONNECT_TIMING);
-                put(Log.Events.Timings.HOLD_TIMING,
+                put(LogUtils.Events.Timings.HOLD_TIMING,
                         ParcelableCallAnalytics.EventTiming.HOLD_TIMING);
-                put(Log.Events.Timings.UNHOLD_TIMING,
+                put(LogUtils.Events.Timings.UNHOLD_TIMING,
                         ParcelableCallAnalytics.EventTiming.UNHOLD_TIMING);
-                put(Log.Events.Timings.OUTGOING_TIME_TO_DIALING_TIMING,
+                put(LogUtils.Events.Timings.OUTGOING_TIME_TO_DIALING_TIMING,
                         ParcelableCallAnalytics.EventTiming.OUTGOING_TIME_TO_DIALING_TIMING);
-                put(Log.Events.Timings.BIND_CS_TIMING,
+                put(LogUtils.Events.Timings.BIND_CS_TIMING,
                         ParcelableCallAnalytics.EventTiming.BIND_CS_TIMING);
-                put(Log.Events.Timings.SCREENING_COMPLETED_TIMING,
+                put(LogUtils.Events.Timings.SCREENING_COMPLETED_TIMING,
                         ParcelableCallAnalytics.EventTiming.SCREENING_COMPLETED_TIMING);
-                put(Log.Events.Timings.DIRECT_TO_VM_FINISHED_TIMING,
+                put(LogUtils.Events.Timings.DIRECT_TO_VM_FINISHED_TIMING,
                         ParcelableCallAnalytics.EventTiming.DIRECT_TO_VM_FINISHED_TIMING);
-                put(Log.Events.Timings.BLOCK_CHECK_FINISHED_TIMING,
+                put(LogUtils.Events.Timings.BLOCK_CHECK_FINISHED_TIMING,
                         ParcelableCallAnalytics.EventTiming.BLOCK_CHECK_FINISHED_TIMING);
-                put(Log.Events.Timings.FILTERING_COMPLETED_TIMING,
+                put(LogUtils.Events.Timings.FILTERING_COMPLETED_TIMING,
                         ParcelableCallAnalytics.EventTiming.FILTERING_COMPLETED_TIMING);
-                put(Log.Events.Timings.FILTERING_TIMED_OUT_TIMING,
+                put(LogUtils.Events.Timings.FILTERING_TIMED_OUT_TIMING,
                         ParcelableCallAnalytics.EventTiming.FILTERING_TIMED_OUT_TIMING);
             }};
 
@@ -169,7 +173,7 @@
         public void setCallConnectionService(String connectionServiceName) {
         }
 
-        public void setCallEvents(Log.CallEventRecord records) {
+        public void setCallEvents(EventManager.EventRecord records) {
         }
 
         public void setCallIsVideo(boolean isVideo) {
@@ -210,7 +214,7 @@
         public String connectionService;
         public boolean isEmergency = false;
 
-        public Log.CallEventRecord callEvents;
+        public EventManager.EventRecord callEvents;
 
         public boolean isVideo = false;
         public List<TelecomLogClass.VideoEvent> videoEvents;
@@ -309,7 +313,7 @@
         }
 
         @Override
-        public void setCallEvents(Log.CallEventRecord records) {
+        public void setCallEvents(EventManager.EventRecord records) {
             this.callEvents = records;
         }
 
@@ -638,10 +642,10 @@
     }
 
     private static TelecomLogClass.Event[] convertLogEventsToProtoEvents(
-            List<Log.CallEvent> logEvents) {
+            List<EventManager.Event> logEvents) {
         long timeOfLastEvent = -1;
         ArrayList<TelecomLogClass.Event> events = new ArrayList<>(logEvents.size());
-        for (Log.CallEvent logEvent : logEvents) {
+        for (EventManager.Event logEvent : logEvents) {
             if (sLogEventToAnalyticsEvent.containsKey(logEvent.eventId)) {
                 TelecomLogClass.Event event = new TelecomLogClass.Event();
                 event.setEventName(sLogEventToAnalyticsEvent.get(logEvent.eventId));
@@ -655,7 +659,7 @@
     }
 
     private static TelecomLogClass.EventTimingEntry logEventTimingToProtoEventTiming(
-            Log.CallEventRecord.EventTiming logEventTiming) {
+            EventManager.EventRecord.EventTiming logEventTiming) {
         int analyticsEventTimingName =
                 sLogEventTimingToAnalyticsEventTiming.containsKey(logEventTiming.name) ?
                         sLogEventTimingToAnalyticsEventTiming.get(logEventTiming.name) :
diff --git a/src/com/android/server/telecom/AsyncRingtonePlayer.java b/src/com/android/server/telecom/AsyncRingtonePlayer.java
index d2a7614..7ed1c85 100644
--- a/src/com/android/server/telecom/AsyncRingtonePlayer.java
+++ b/src/com/android/server/telecom/AsyncRingtonePlayer.java
@@ -21,6 +21,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Message;
+import android.telecom.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.SomeArgs;
@@ -137,8 +138,8 @@
                 Uri ringtoneUri = incomingCall.getRingtone();
                 String ringtoneUriString = (ringtoneUri == null) ? "null" :
                         ringtoneUri.toSafeString();
-                Log.event(null, Log.Events.ERROR_LOG, "Failed to get ringtone from factory. " +
-                        "Skipping ringing. Uri was: " + ringtoneUriString);
+                Log.addEvent(null, LogUtils.Events.ERROR_LOG, "Failed to get ringtone from " +
+                        "factory. Skipping ringing. Uri was: " + ringtoneUriString);
                 return;
             }
         }
diff --git a/src/com/android/server/telecom/BluetoothManager.java b/src/com/android/server/telecom/BluetoothManager.java
index d31c69d..d043cc5 100644
--- a/src/com/android/server/telecom/BluetoothManager.java
+++ b/src/com/android/server/telecom/BluetoothManager.java
@@ -26,6 +26,8 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.SystemClock;
+import android.telecom.Log;
+import android.telecom.Logging.Runnable;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
diff --git a/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java b/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
index c79b036..2173fa5 100644
--- a/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
+++ b/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
@@ -29,6 +29,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.telecom.Connection;
+import android.telecom.Log;
 import android.telecom.PhoneAccount;
 import android.telecom.VideoProfile;
 import android.telephony.PhoneNumberUtils;
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 139190c..ac7bfdc 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -29,6 +29,8 @@
 import android.telecom.DisconnectCause;
 import android.telecom.Connection;
 import android.telecom.GatewayInfo;
+import android.telecom.Log;
+import android.telecom.Logging.EventManager;
 import android.telecom.ParcelableConnection;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
@@ -47,8 +49,10 @@
 import com.android.internal.util.Preconditions;
 
 import java.lang.String;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Date;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
@@ -62,7 +66,7 @@
  *  connected etc).
  */
 @VisibleForTesting
-public class Call implements CreateConnectionResponse {
+public class Call implements CreateConnectionResponse, EventManager.Loggable {
     public final static String CALL_ID_UNKNOWN = "-1";
     public final static long DATA_USAGE_NOT_SET = -1;
 
@@ -507,7 +511,7 @@
                 analyticsDirection = Analytics.UNKNOWN_DIRECTION;
         }
         mAnalytics = Analytics.initiateCallAnalytics(mId, analyticsDirection);
-        Log.event(this, Log.Events.CREATED);
+        Log.addEvent(this, LogUtils.Events.CREATED);
     }
 
     public Analytics.CallInfo getAnalytics() {
@@ -515,7 +519,7 @@
     }
 
     public void destroy() {
-        Log.event(this, Log.Events.DESTROYED);
+        Log.addEvent(this, LogUtils.Events.DESTROYED);
     }
 
     /** {@inheritDoc} */
@@ -538,6 +542,20 @@
                 Connection.propertiesToString(getConnectionProperties()));
     }
 
+    @Override
+    public String getDescription() {
+        StringBuilder s = new StringBuilder("Call ");
+        s.append(getId());
+        s.append(" [");
+        s.append(SimpleDateFormat.getDateTimeInstance().format(new Date(getCreationTimeMillis())));
+        s.append("]");
+        s.append(isIncoming() ? "(MT - incoming)" : "(MO - outgoing)");
+        s.append("\n\tTo address: ");
+        s.append(Log.piiHandle(getHandle()));
+        s.append("\n");
+        return s.toString();
+    }
+
     /**
      * Builds a debug-friendly description string for a video state.
      * <p>
@@ -674,32 +692,32 @@
             Object data = null;
             switch (newState) {
                 case CallState.ACTIVE:
-                    event = Log.Events.SET_ACTIVE;
+                    event = LogUtils.Events.SET_ACTIVE;
                     break;
                 case CallState.CONNECTING:
-                    event = Log.Events.SET_CONNECTING;
+                    event = LogUtils.Events.SET_CONNECTING;
                     break;
                 case CallState.DIALING:
-                    event = Log.Events.SET_DIALING;
+                    event = LogUtils.Events.SET_DIALING;
                     break;
                 case CallState.PULLING:
-                    event = Log.Events.SET_PULLING;
+                    event = LogUtils.Events.SET_PULLING;
                     break;
                 case CallState.DISCONNECTED:
-                    event = Log.Events.SET_DISCONNECTED;
+                    event = LogUtils.Events.SET_DISCONNECTED;
                     data = getDisconnectCause();
                     break;
                 case CallState.DISCONNECTING:
-                    event = Log.Events.SET_DISCONNECTING;
+                    event = LogUtils.Events.SET_DISCONNECTING;
                     break;
                 case CallState.ON_HOLD:
-                    event = Log.Events.SET_HOLD;
+                    event = LogUtils.Events.SET_HOLD;
                     break;
                 case CallState.SELECT_PHONE_ACCOUNT:
-                    event = Log.Events.SET_SELECT_PHONE_ACCOUNT;
+                    event = LogUtils.Events.SET_SELECT_PHONE_ACCOUNT;
                     break;
                 case CallState.RINGING:
-                    event = Log.Events.SET_RINGING;
+                    event = LogUtils.Events.SET_RINGING;
                     break;
             }
             if (event != null) {
@@ -709,7 +727,7 @@
                     // If data exists, add it to tag.  If no tag, just use data.toString().
                     stringData = stringData == null ? data.toString() : stringData + "> " + data;
                 }
-                Log.event(this, event, stringData);
+                Log.addEvent(this, event, stringData);
             }
         }
     }
@@ -1035,7 +1053,7 @@
             }
 
             int xorCaps = previousCapabilities ^ mConnectionCapabilities;
-            Log.event(this, Log.Events.CAPABILITY_CHANGE,
+            Log.addEvent(this, LogUtils.Events.CAPABILITY_CHANGE,
                     "Current: [%s], Removed [%s], Added [%s]",
                     Connection.capabilitiesToStringShort(mConnectionCapabilities),
                     Connection.capabilitiesToStringShort(previousCapabilities & xorCaps),
@@ -1060,7 +1078,7 @@
             if (wasExternal != isExternal) {
                 Log.v(this, "setConnectionProperties: external call changed isExternal = %b",
                         isExternal);
-                Log.event(this, Log.Events.IS_EXTERNAL, isExternal);
+                Log.addEvent(this, LogUtils.Events.IS_EXTERNAL, isExternal);
                 for (Listener l : mListeners) {
                     l.onExternalCallChanged(this, isExternal);
                 }
@@ -1070,7 +1088,7 @@
             mAnalytics.addCallProperties(mConnectionProperties);
 
             int xorProps = previousProperties ^ mConnectionProperties;
-            Log.event(this, Log.Events.PROPERTY_CHANGE,
+            Log.addEvent(this, LogUtils.Events.PROPERTY_CHANGE,
                     "Current: [%s], Removed [%s], Added [%s]",
                     Connection.propertiesToStringShort(mConnectionProperties),
                     Connection.propertiesToStringShort(previousProperties & xorProps),
@@ -1243,7 +1261,7 @@
         } else {
             Log.i(this, "Send playDtmfTone to connection service for call %s", this);
             mConnectionService.playDtmfTone(this, digit);
-            Log.event(this, Log.Events.START_DTMF, Log.pii(digit));
+            Log.addEvent(this, LogUtils.Events.START_DTMF, Log.pii(digit));
         }
     }
 
@@ -1255,7 +1273,7 @@
             Log.w(this, "stopDtmfTone() request on a call without a connection service.");
         } else {
             Log.i(this, "Send stopDtmfTone to connection service for call %s", this);
-            Log.event(this, Log.Events.STOP_DTMF);
+            Log.addEvent(this, LogUtils.Events.STOP_DTMF);
             mConnectionService.stopDtmfTone(this);
         }
     }
@@ -1268,7 +1286,7 @@
             Log.w(this, "silence() request on a call without a connection service.");
         } else {
             Log.i(this, "Send silence to connection service for call %s", this);
-            Log.event(this, Log.Events.SILENCE);
+            Log.addEvent(this, LogUtils.Events.SILENCE);
             mConnectionService.silence(this);
         }
     }
@@ -1283,7 +1301,7 @@
      */
     @VisibleForTesting
     public void disconnect(boolean wasViaNewOutgoingCallBroadcaster) {
-        Log.event(this, Log.Events.REQUEST_DISCONNECT);
+        Log.addEvent(this, LogUtils.Events.REQUEST_DISCONNECT);
 
         // Track that the call is now locally disconnecting.
         setLocallyDisconnecting(true);
@@ -1363,7 +1381,7 @@
                 Log.e(this, new NullPointerException(),
                         "answer call failed due to null CS callId=%s", getId());
             }
-            Log.event(this, Log.Events.REQUEST_ACCEPT);
+            Log.addEvent(this, LogUtils.Events.REQUEST_ACCEPT);
         }
     }
 
@@ -1387,7 +1405,7 @@
                 Log.e(this, new NullPointerException(),
                         "reject call failed due to null CS callId=%s", getId());
             }
-            Log.event(this, Log.Events.REQUEST_REJECT);
+            Log.addEvent(this, LogUtils.Events.REQUEST_REJECT);
 
         }
     }
@@ -1403,7 +1421,7 @@
                 Log.e(this, new NullPointerException(),
                         "hold call failed due to null CS callId=%s", getId());
             }
-            Log.event(this, Log.Events.REQUEST_HOLD);
+            Log.addEvent(this, LogUtils.Events.REQUEST_HOLD);
         }
     }
 
@@ -1418,7 +1436,7 @@
                 Log.e(this, new NullPointerException(),
                         "unhold call failed due to null CS callId=%s", getId());
             }
-            Log.event(this, Log.Events.REQUEST_UNHOLD);
+            Log.addEvent(this, LogUtils.Events.REQUEST_UNHOLD);
         }
     }
 
@@ -1564,7 +1582,7 @@
         if (mConnectionService == null) {
             Log.w(this, "conference requested on a call without a connection service.");
         } else {
-            Log.event(this, Log.Events.CONFERENCE_WITH, otherCall);
+            Log.addEvent(this, LogUtils.Events.CONFERENCE_WITH, otherCall);
             mConnectionService.conference(this, otherCall);
         }
     }
@@ -1573,7 +1591,7 @@
         if (mConnectionService == null) {
             Log.w(this, "splitting from conference call without a connection service");
         } else {
-            Log.event(this, Log.Events.SPLIT_FROM_CONFERENCE);
+            Log.addEvent(this, LogUtils.Events.SPLIT_FROM_CONFERENCE);
             mConnectionService.splitFromConference(this);
         }
     }
@@ -1583,7 +1601,7 @@
         if (mConnectionService == null) {
             Log.w(this, "merging conference calls without a connection service.");
         } else if (can(Connection.CAPABILITY_MERGE_CONFERENCE)) {
-            Log.event(this, Log.Events.CONFERENCE_WITH);
+            Log.addEvent(this, LogUtils.Events.CONFERENCE_WITH);
             mConnectionService.mergeConference(this);
             mWasConferencePreviouslyMerged = true;
         }
@@ -1594,7 +1612,7 @@
         if (mConnectionService == null) {
             Log.w(this, "swapping conference calls without a connection service.");
         } else if (can(Connection.CAPABILITY_SWAP_CONFERENCE)) {
-            Log.event(this, Log.Events.SWAP);
+            Log.addEvent(this, LogUtils.Events.SWAP);
             mConnectionService.swapConference(this);
             switch (mChildCalls.size()) {
                 case 1:
@@ -1645,8 +1663,7 @@
             Log.w(this, "pullExternalCall - call %s is external but cannot be pulled.", mId);
             return;
         }
-
-        Log.event(this, Log.Events.REQUEST_PULL);
+        Log.addEvent(this, LogUtils.Events.REQUEST_PULL);
         mConnectionService.pullExternalCall(this);
     }
 
@@ -1687,7 +1704,7 @@
             mParentCall.addChildCall(this);
         }
 
-        Log.event(this, Log.Events.SET_PARENT, mParentCall);
+        Log.addEvent(this, LogUtils.Events.SET_PARENT, mParentCall);
         for (Listener l : mListeners) {
             l.onParentChanged(this);
         }
@@ -1724,7 +1741,7 @@
             mConferenceLevelActiveCall = call;
             mChildCalls.add(call);
 
-            Log.event(this, Log.Events.ADD_CHILD, call);
+            Log.addEvent(this, LogUtils.Events.ADD_CHILD, call);
 
             for (Listener l : mListeners) {
                 l.onChildrenChanged(this);
@@ -1734,7 +1751,7 @@
 
     private void removeChildCall(Call call) {
         if (mChildCalls.remove(call)) {
-            Log.event(this, Log.Events.REMOVE_CHILD, call);
+            Log.addEvent(this, LogUtils.Events.REMOVE_CHILD, call);
             for (Listener l : mListeners) {
                 l.onChildrenChanged(this);
             }
@@ -2010,7 +2027,7 @@
         int previousVideoState = mVideoState;
         mVideoState = videoState;
         if (mVideoState != previousVideoState) {
-            Log.event(this, Log.Events.VIDEO_STATE_CHANGED,
+            Log.addEvent(this, LogUtils.Events.VIDEO_STATE_CHANGED,
                     VideoProfile.videoStateToString(videoState));
             for (Listener l : mListeners) {
                 l.onVideoStateChanged(this, previousVideoState, mVideoState);
@@ -2168,10 +2185,10 @@
      * @param extras The extras.
      */
     public void onConnectionEvent(String event, Bundle extras) {
-        Log.event(this, Log.Events.CONNECTION_EVENT, event);
+        Log.addEvent(this, LogUtils.Events.CONNECTION_EVENT, event);
         if (Connection.EVENT_ON_HOLD_TONE_START.equals(event)) {
             mIsRemotelyHeld = true;
-            Log.event(this, Log.Events.REMOTELY_HELD);
+            Log.addEvent(this, LogUtils.Events.REMOTELY_HELD);
             // Inform listeners of the fact that a call hold tone was received.  This will trigger
             // the CallAudioManager to play a tone via the InCallTonePlayer.
             for (Listener l : mListeners) {
@@ -2179,7 +2196,7 @@
             }
         } else if (Connection.EVENT_ON_HOLD_TONE_END.equals(event)) {
             mIsRemotelyHeld = false;
-            Log.event(this, Log.Events.REMOTELY_UNHELD);
+            Log.addEvent(this, LogUtils.Events.REMOTELY_UNHELD);
             for (Listener l : mListeners) {
                 l.onHoldToneRequested(this);
             }
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index 236df5f..4a35acc 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -20,6 +20,7 @@
 import android.media.IAudioService;
 import android.media.ToneGenerator;
 import android.telecom.CallAudioState;
+import android.telecom.Log;
 import android.telecom.VideoProfile;
 import android.util.SparseArray;
 
diff --git a/src/com/android/server/telecom/CallAudioModeStateMachine.java b/src/com/android/server/telecom/CallAudioModeStateMachine.java
index 57043bc..0a222cc 100644
--- a/src/com/android/server/telecom/CallAudioModeStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioModeStateMachine.java
@@ -18,6 +18,9 @@
 
 import android.media.AudioManager;
 import android.os.Message;
+import android.telecom.Log;
+import android.telecom.Logging.Runnable;
+import android.telecom.Logging.Session;
 import android.util.SparseArray;
 
 import com.android.internal.util.IState;
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index ce03e61..5cb59c4 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -32,6 +32,8 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.telecom.CallAudioState;
+import android.telecom.Log;
+import android.telecom.Logging.Session;
 import android.util.SparseArray;
 
 import com.android.internal.util.IState;
@@ -113,10 +115,10 @@
     public static final int RINGING_FOCUS = 3;
 
     private static final SparseArray<String> AUDIO_ROUTE_TO_LOG_EVENT = new SparseArray<String>() {{
-        put(CallAudioState.ROUTE_BLUETOOTH, Log.Events.AUDIO_ROUTE_BT);
-        put(CallAudioState.ROUTE_EARPIECE, Log.Events.AUDIO_ROUTE_EARPIECE);
-        put(CallAudioState.ROUTE_SPEAKER, Log.Events.AUDIO_ROUTE_SPEAKER);
-        put(CallAudioState.ROUTE_WIRED_HEADSET, Log.Events.AUDIO_ROUTE_HEADSET);
+        put(CallAudioState.ROUTE_BLUETOOTH, LogUtils.Events.AUDIO_ROUTE_BT);
+        put(CallAudioState.ROUTE_EARPIECE, LogUtils.Events.AUDIO_ROUTE_EARPIECE);
+        put(CallAudioState.ROUTE_SPEAKER, LogUtils.Events.AUDIO_ROUTE_SPEAKER);
+        put(CallAudioState.ROUTE_WIRED_HEADSET, LogUtils.Events.AUDIO_ROUTE_HEADSET);
     }};
 
     private static final SparseArray<String> MESSAGE_CODE_TO_NAME = new SparseArray<String>() {{
@@ -209,13 +211,13 @@
         @Override
         public void enter() {
             super.enter();
-            Log.event(mCallsManager.getForegroundCall(), Log.Events.AUDIO_ROUTE,
+            Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE,
                     "Entering state " + getName());
         }
 
         @Override
         public void exit() {
-            Log.event(mCallsManager.getForegroundCall(), Log.Events.AUDIO_ROUTE,
+            Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE,
                     "Leaving state " + getName());
             super.exit();
         }
@@ -224,18 +226,18 @@
         public boolean processMessage(Message msg) {
             switch (msg.what) {
                 case CONNECT_WIRED_HEADSET:
-                    Log.event(mCallsManager.getForegroundCall(), Log.Events.AUDIO_ROUTE,
+                    Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE,
                             "Wired headset connected");
                     mAvailableRoutes &= ~ROUTE_EARPIECE;
                     mAvailableRoutes |= ROUTE_WIRED_HEADSET;
                     return NOT_HANDLED;
                 case CONNECT_BLUETOOTH:
-                    Log.event(mCallsManager.getForegroundCall(), Log.Events.AUDIO_ROUTE,
+                    Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE,
                             "Bluetooth connected");
                     mAvailableRoutes |= ROUTE_BLUETOOTH;
                     return NOT_HANDLED;
                 case DISCONNECT_WIRED_HEADSET:
-                    Log.event(mCallsManager.getForegroundCall(), Log.Events.AUDIO_ROUTE,
+                    Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE,
                             "Wired headset disconnected");
                     mAvailableRoutes &= ~ROUTE_WIRED_HEADSET;
                     if (mDoesDeviceSupportEarpieceRoute) {
@@ -243,7 +245,7 @@
                     }
                     return NOT_HANDLED;
                 case DISCONNECT_BLUETOOTH:
-                    Log.event(mCallsManager.getForegroundCall(), Log.Events.AUDIO_ROUTE,
+                    Log.addEvent(mCallsManager.getForegroundCall(), LogUtils.Events.AUDIO_ROUTE,
                             "Bluetooth disconnected");
                     mAvailableRoutes &= ~ROUTE_BLUETOOTH;
                     return NOT_HANDLED;
@@ -1344,8 +1346,8 @@
 
     private void setMuteOn(boolean mute) {
         mIsMuted = mute;
-        Log.event(mCallsManager.getForegroundCall(), mute ? Log.Events.MUTE : Log.Events.UNMUTE);
-
+        Log.addEvent(mCallsManager.getForegroundCall(), mute ?
+                LogUtils.Events.MUTE : LogUtils.Events.UNMUTE);
         if (mute != mAudioManager.isMicrophoneMute() && isInActiveState()) {
             IAudioService audio = mAudioServiceFactory.getAudioService();
             Log.i(this, "changing microphone mute state to: %b [serviceIsNull=%b]",
@@ -1401,9 +1403,9 @@
                     newCallAudioState);
             if (force || !newCallAudioState.equals(mLastKnownCallAudioState)) {
                 if (newCallAudioState.getRoute() != mLastKnownCallAudioState.getRoute()) {
-                    Log.event(mCallsManager.getForegroundCall(),
+                    Log.addEvent(mCallsManager.getForegroundCall(),
                             AUDIO_ROUTE_TO_LOG_EVENT.get(newCallAudioState.getRoute(),
-                                    Log.Events.AUDIO_ROUTE));
+                                    LogUtils.Events.AUDIO_ROUTE));
                 }
 
                 mCallsManager.onCallAudioStateChanged(mLastKnownCallAudioState, newCallAudioState);
diff --git a/src/com/android/server/telecom/CallIntentProcessor.java b/src/com/android/server/telecom/CallIntentProcessor.java
index 1219216..2126c48 100644
--- a/src/com/android/server/telecom/CallIntentProcessor.java
+++ b/src/com/android/server/telecom/CallIntentProcessor.java
@@ -11,6 +11,7 @@
 import android.os.UserManager;
 import android.telecom.Connection;
 import android.telecom.DefaultDialerManager;
+import android.telecom.Log;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
diff --git a/src/com/android/server/telecom/CallLogManager.java b/src/com/android/server/telecom/CallLogManager.java
index 64e266d..d89f54a 100755
--- a/src/com/android/server/telecom/CallLogManager.java
+++ b/src/com/android/server/telecom/CallLogManager.java
@@ -29,6 +29,7 @@
 import android.os.PersistableBundle;
 import android.provider.CallLog.Calls;
 import android.telecom.DisconnectCause;
+import android.telecom.Log;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.VideoProfile;
diff --git a/src/com/android/server/telecom/CallerInfoLookupHelper.java b/src/com/android/server/telecom/CallerInfoLookupHelper.java
index 244a802..f67a7f7 100644
--- a/src/com/android/server/telecom/CallerInfoLookupHelper.java
+++ b/src/com/android/server/telecom/CallerInfoLookupHelper.java
@@ -23,6 +23,9 @@
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
+import android.telecom.Log;
+import android.telecom.Logging.Runnable;
+import android.telecom.Logging.Session;
 import android.text.TextUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index f66fedf..81f77cd 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -40,10 +40,12 @@
 import android.telecom.Connection;
 import android.telecom.DisconnectCause;
 import android.telecom.GatewayInfo;
+import android.telecom.Log;
 import android.telecom.ParcelableConference;
 import android.telecom.ParcelableConnection;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
+import android.telecom.Logging.Runnable;
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
 import android.telephony.PhoneNumberUtils;
@@ -1248,12 +1250,12 @@
                 // Only attempt to hold parent calls and not the individual children.
                 if (c != null && c.isAlive() && c != call && c.getParentCall() == null) {
                     otherCallHeld = true;
-                    Log.event(c, Log.Events.SWAP);
+                    Log.addEvent(c, LogUtils.Events.SWAP);
                     c.hold();
                 }
             }
             if (otherCallHeld) {
-                Log.event(call, Log.Events.SWAP);
+                Log.addEvent(call, LogUtils.Events.SWAP);
             }
             call.unhold();
         }
@@ -1515,7 +1517,8 @@
                 if (ringingCall == null) {
                     Call callToHangup = getFirstCallWithState(CallState.RINGING, CallState.DIALING,
                             CallState.PULLING, CallState.ACTIVE, CallState.ON_HOLD);
-                    Log.event(callToHangup, Log.Events.INFO, "media btn short press - end call.");
+                    Log.addEvent(callToHangup, LogUtils.Events.INFO,
+                            "media btn short press - end call.");
                     if (callToHangup != null) {
                         callToHangup.disconnect();
                         return true;
@@ -1526,11 +1529,12 @@
                 }
             } else if (HeadsetMediaButton.LONG_PRESS == type) {
                 if (ringingCall != null) {
-                    Log.event(
-                            getForegroundCall(), Log.Events.INFO, "media btn long press - reject");
+                    Log.addEvent(getForegroundCall(),
+                            LogUtils.Events.INFO, "media btn long press - reject");
                     ringingCall.reject(false, null);
                 } else {
-                    Log.event(getForegroundCall(), Log.Events.INFO, "media btn long press - mute");
+                    Log.addEvent(getForegroundCall(), LogUtils.Events.INFO,
+                            "media btn long press - mute");
                     mCallAudioManager.toggleMute();
                 }
                 return true;
@@ -1779,11 +1783,11 @@
         updateCanAddCall();
         // onCallAdded for calls which immediately take the foreground (like the first call).
         for (CallsManagerListener listener : mListeners) {
-            if (Log.SYSTRACE_DEBUG) {
+            if (LogUtils.SYSTRACE_DEBUG) {
                 Trace.beginSection(listener.getClass().toString() + " addCall");
             }
             listener.onCallAdded(call);
-            if (Log.SYSTRACE_DEBUG) {
+            if (LogUtils.SYSTRACE_DEBUG) {
                 Trace.endSection();
             }
         }
@@ -1810,11 +1814,11 @@
         if (shouldNotify) {
             updateCanAddCall();
             for (CallsManagerListener listener : mListeners) {
-                if (Log.SYSTRACE_DEBUG) {
+                if (LogUtils.SYSTRACE_DEBUG) {
                     Trace.beginSection(listener.getClass().toString() + " onCallRemoved");
                 }
                 listener.onCallRemoved(call);
-                if (Log.SYSTRACE_DEBUG) {
+                if (LogUtils.SYSTRACE_DEBUG) {
                     Trace.endSection();
                 }
             }
@@ -1851,11 +1855,11 @@
             if (mCalls.contains(call)) {
                 updateCanAddCall();
                 for (CallsManagerListener listener : mListeners) {
-                    if (Log.SYSTRACE_DEBUG) {
+                    if (LogUtils.SYSTRACE_DEBUG) {
                         Trace.beginSection(listener.getClass().toString() + " onCallStateChanged");
                     }
                     listener.onCallStateChanged(call, oldState, newState);
-                    if (Log.SYSTRACE_DEBUG) {
+                    if (LogUtils.SYSTRACE_DEBUG) {
                         Trace.endSection();
                     }
                 }
@@ -1869,11 +1873,11 @@
         if (newCanAddCall != mCanAddCall) {
             mCanAddCall = newCanAddCall;
             for (CallsManagerListener listener : mListeners) {
-                if (Log.SYSTRACE_DEBUG) {
+                if (LogUtils.SYSTRACE_DEBUG) {
                     Trace.beginSection(listener.getClass().toString() + " updateCanAddCall");
                 }
                 listener.onCanAddCallChanged(mCanAddCall);
-                if (Log.SYSTRACE_DEBUG) {
+                if (LogUtils.SYSTRACE_DEBUG) {
                     Trace.endSection();
                 }
             }
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index bf82a99..027b547 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -31,6 +31,7 @@
 import android.telecom.ConnectionService;
 import android.telecom.DisconnectCause;
 import android.telecom.GatewayInfo;
+import android.telecom.Log;
 import android.telecom.ParcelableConference;
 import android.telecom.ParcelableConnection;
 import android.telecom.PhoneAccount;
@@ -68,7 +69,7 @@
         @Override
         public void handleCreateConnectionComplete(String callId, ConnectionRequest request,
                 ParcelableConnection connection) {
-            Log.startSession(Log.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE);
+            Log.startSession(LogUtils.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -84,7 +85,7 @@
 
         @Override
         public void setActive(String callId) {
-            Log.startSession(Log.Sessions.CSW_SET_ACTIVE);
+            Log.startSession(LogUtils.Sessions.CSW_SET_ACTIVE);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -104,7 +105,7 @@
 
         @Override
         public void setRinging(String callId) {
-            Log.startSession(Log.Sessions.CSW_SET_RINGING);
+            Log.startSession(LogUtils.Sessions.CSW_SET_RINGING);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -142,7 +143,7 @@
 
         @Override
         public void setDialing(String callId) {
-            Log.startSession(Log.Sessions.CSW_SET_DIALING);
+            Log.startSession(LogUtils.Sessions.CSW_SET_DIALING);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -162,7 +163,7 @@
 
         @Override
         public void setPulling(String callId) {
-            Log.startSession(Log.Sessions.CSW_SET_PULLING);
+            Log.startSession(LogUtils.Sessions.CSW_SET_PULLING);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -180,7 +181,7 @@
 
         @Override
         public void setDisconnected(String callId, DisconnectCause disconnectCause) {
-            Log.startSession(Log.Sessions.CSW_SET_DISCONNECTED);
+            Log.startSession(LogUtils.Sessions.CSW_SET_DISCONNECTED);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -201,7 +202,7 @@
 
         @Override
         public void setOnHold(String callId) {
-            Log.startSession(Log.Sessions.CSW_SET_ON_HOLD);
+            Log.startSession(LogUtils.Sessions.CSW_SET_ON_HOLD);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -241,7 +242,7 @@
 
         @Override
         public void removeCall(String callId) {
-            Log.startSession(Log.Sessions.CSW_REMOVE_CALL);
+            Log.startSession(LogUtils.Sessions.CSW_REMOVE_CALL);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -303,7 +304,7 @@
 
         @Override
         public void setIsConferenced(String callId, String conferenceCallId) {
-            Log.startSession(Log.Sessions.CSW_SET_IS_CONFERENCED);
+            Log.startSession(LogUtils.Sessions.CSW_SET_IS_CONFERENCED);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -352,7 +353,7 @@
 
         @Override
         public void addConferenceCall(String callId, ParcelableConference parcelableConference) {
-            Log.startSession(Log.Sessions.CSW_ADD_CONFERENCE_CALL);
+            Log.startSession(LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -767,7 +768,7 @@
                             gatewayInfo.getOriginalAddress());
                 }
 
-                Log.event(call, Log.Events.START_CONNECTION, Log.piiHandle(call.getHandle()));
+                Log.addEvent(call, LogUtils.Events.START_CONNECTION, Log.piiHandle(call.getHandle()));
                 try {
                     mServiceInterface.createConnection(
                             call.getConnectionManagerPhoneAccount(),
diff --git a/src/com/android/server/telecom/ContactsAsyncHelper.java b/src/com/android/server/telecom/ContactsAsyncHelper.java
index 6f8c86c..7fb6419 100644
--- a/src/com/android/server/telecom/ContactsAsyncHelper.java
+++ b/src/com/android/server/telecom/ContactsAsyncHelper.java
@@ -21,6 +21,7 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.telecom.Log;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.HandlerThread;
diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java
index 22ec3c6..2b88848 100644
--- a/src/com/android/server/telecom/CreateConnectionProcessor.java
+++ b/src/com/android/server/telecom/CreateConnectionProcessor.java
@@ -17,8 +17,8 @@
 package com.android.server.telecom;
 
 import android.content.Context;
-import android.os.UserHandle;
 import android.telecom.DisconnectCause;
+import android.telecom.Log;
 import android.telecom.ParcelableConnection;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
diff --git a/src/com/android/server/telecom/CreateConnectionTimeout.java b/src/com/android/server/telecom/CreateConnectionTimeout.java
index 8bc3373..399c28a 100644
--- a/src/com/android/server/telecom/CreateConnectionTimeout.java
+++ b/src/com/android/server/telecom/CreateConnectionTimeout.java
@@ -19,7 +19,8 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.UserHandle;
+import android.telecom.Log;
+import android.telecom.Logging.Runnable;
 import android.telecom.PhoneAccountHandle;
 import android.telephony.TelephonyManager;
 
diff --git a/src/com/android/server/telecom/DialerCodeReceiver.java b/src/com/android/server/telecom/DialerCodeReceiver.java
index 8732222..57f84a0 100644
--- a/src/com/android/server/telecom/DialerCodeReceiver.java
+++ b/src/com/android/server/telecom/DialerCodeReceiver.java
@@ -19,6 +19,7 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.telecom.Log;
 import android.telecom.TelecomManager;
 
 /**
@@ -59,7 +60,7 @@
                 // If there is an active call, add the "log mark" for that call; otherwise we will
                 // add a non-call event.
                 Call currentCall = mCallsManager.getActiveCall();
-                Log.event(currentCall, Log.Events.USER_LOG_MARK);
+                Log.addEvent(currentCall, LogUtils.Events.USER_LOG_MARK);
             }
         }
     }
diff --git a/src/com/android/server/telecom/DockManager.java b/src/com/android/server/telecom/DockManager.java
index 27ffd28..46b2efc 100644
--- a/src/com/android/server/telecom/DockManager.java
+++ b/src/com/android/server/telecom/DockManager.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.telecom.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
diff --git a/src/com/android/server/telecom/DtmfLocalTonePlayer.java b/src/com/android/server/telecom/DtmfLocalTonePlayer.java
index 64c0c55..5abbf49 100644
--- a/src/com/android/server/telecom/DtmfLocalTonePlayer.java
+++ b/src/com/android/server/telecom/DtmfLocalTonePlayer.java
@@ -23,6 +23,7 @@
 import android.os.HandlerThread;
 import android.os.Message;
 import android.provider.Settings;
+import android.telecom.Log;
 
 import com.android.internal.util.Preconditions;
 
diff --git a/src/com/android/server/telecom/HeadsetMediaButton.java b/src/com/android/server/telecom/HeadsetMediaButton.java
index 700bba1..7d6a798 100644
--- a/src/com/android/server/telecom/HeadsetMediaButton.java
+++ b/src/com/android/server/telecom/HeadsetMediaButton.java
@@ -23,6 +23,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.telecom.Log;
 import android.view.KeyEvent;
 
 /**
diff --git a/src/com/android/server/telecom/InCallAdapter.java b/src/com/android/server/telecom/InCallAdapter.java
index e47f3a2..e775818 100644
--- a/src/com/android/server/telecom/InCallAdapter.java
+++ b/src/com/android/server/telecom/InCallAdapter.java
@@ -18,6 +18,7 @@
 
 import android.os.Binder;
 import android.os.Bundle;
+import android.telecom.Log;
 import android.telecom.PhoneAccountHandle;
 
 import com.android.internal.telecom.IInCallAdapter;
@@ -47,7 +48,7 @@
     @Override
     public void answerCall(String callId, int videoState) {
         try {
-            Log.startSession(Log.Sessions.ICA_ANSWER_CALL, mOwnerComponentName);
+            Log.startSession(LogUtils.Sessions.ICA_ANSWER_CALL, mOwnerComponentName);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -70,7 +71,7 @@
     @Override
     public void rejectCall(String callId, boolean rejectWithMessage, String textMessage) {
         try {
-            Log.startSession(Log.Sessions.ICA_REJECT_CALL, mOwnerComponentName);
+            Log.startSession(LogUtils.Sessions.ICA_REJECT_CALL, mOwnerComponentName);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -162,7 +163,7 @@
     @Override
     public void disconnectCall(String callId) {
         try {
-            Log.startSession(Log.Sessions.ICA_DISCONNECT_CALL, mOwnerComponentName);
+            Log.startSession(LogUtils.Sessions.ICA_DISCONNECT_CALL, mOwnerComponentName);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -185,7 +186,7 @@
     @Override
     public void holdCall(String callId) {
         try {
-            Log.startSession(Log.Sessions.ICA_HOLD_CALL, mOwnerComponentName);
+            Log.startSession(LogUtils.Sessions.ICA_HOLD_CALL, mOwnerComponentName);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -207,7 +208,7 @@
     @Override
     public void unholdCall(String callId) {
         try {
-            Log.startSession(Log.Sessions.ICA_UNHOLD_CALL, mOwnerComponentName);
+            Log.startSession(LogUtils.Sessions.ICA_UNHOLD_CALL, mOwnerComponentName);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -252,7 +253,7 @@
     @Override
     public void mute(boolean shouldMute) {
         try {
-            Log.startSession(Log.Sessions.ICA_MUTE, mOwnerComponentName);
+            Log.startSession(LogUtils.Sessions.ICA_MUTE, mOwnerComponentName);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -269,7 +270,7 @@
     @Override
     public void setAudioRoute(int route) {
         try {
-            Log.startSession(Log.Sessions.ICA_SET_AUDIO_ROUTE, mOwnerComponentName);
+            Log.startSession(LogUtils.Sessions.ICA_SET_AUDIO_ROUTE, mOwnerComponentName);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
@@ -286,7 +287,7 @@
     @Override
     public void conference(String callId, String otherCallId) {
         try {
-            Log.startSession(Log.Sessions.ICA_CONFERENCE, mOwnerComponentName);
+            Log.startSession(LogUtils.Sessions.ICA_CONFERENCE, mOwnerComponentName);
             long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index 2157bf3..43c0e48 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -36,6 +36,8 @@
 import android.telecom.ConnectionService;
 import android.telecom.DefaultDialerManager;
 import android.telecom.InCallService;
+import android.telecom.Log;
+import android.telecom.Logging.Runnable;
 import android.telecom.ParcelableCall;
 import android.telecom.TelecomManager;
 import android.text.TextUtils;
@@ -178,7 +180,7 @@
         @Override
         public boolean connect(Call call) {
             if (mIsConnected) {
-                Log.event(call, Log.Events.INFO, "Already connected, ignoring request.");
+                Log.addEvent(call, LogUtils.Events.INFO, "Already connected, ignoring request.");
                 return true;
             }
 
@@ -215,7 +217,7 @@
                 mContext.unbindService(mServiceConnection);
                 mIsConnected = false;
             } else {
-                Log.event(null, Log.Events.INFO, "Already disconnected, ignoring request.");
+                Log.addEvent(null, LogUtils.Events.INFO, "Already disconnected, ignoring request.");
             }
         }
 
diff --git a/src/com/android/server/telecom/InCallTonePlayer.java b/src/com/android/server/telecom/InCallTonePlayer.java
index e0b0dc0..62c692b 100644
--- a/src/com/android/server/telecom/InCallTonePlayer.java
+++ b/src/com/android/server/telecom/InCallTonePlayer.java
@@ -20,6 +20,9 @@
 import android.media.ToneGenerator;
 import android.os.Handler;
 import android.os.Looper;
+import android.telecom.Log;
+import android.telecom.Logging.Runnable;
+import android.telecom.Logging.Session;
 
 import com.android.internal.annotations.VisibleForTesting;
 
diff --git a/src/com/android/server/telecom/InCallWakeLockController.java b/src/com/android/server/telecom/InCallWakeLockController.java
index 0de8123..ac93bb5 100644
--- a/src/com/android/server/telecom/InCallWakeLockController.java
+++ b/src/com/android/server/telecom/InCallWakeLockController.java
@@ -17,6 +17,7 @@
 package com.android.server.telecom;
 
 import com.android.internal.annotations.VisibleForTesting;
+import android.telecom.Log;
 
 /**
  * Handles acquisition and release of wake locks relating to call state.
diff --git a/src/com/android/server/telecom/Log.java b/src/com/android/server/telecom/Log.java
deleted file mode 100644
index 011d038..0000000
--- a/src/com/android/server/telecom/Log.java
+++ /dev/null
@@ -1,1030 +0,0 @@
-/*
- * Copyright 2014, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.telecom;
-
-import android.content.Context;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.AsyncTask;
-import android.telecom.PhoneAccount;
-import android.telecom.TimedEvent;
-import android.telephony.PhoneNumberUtils;
-import android.text.TextUtils;
-import android.util.Base64;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.IndentingPrintWriter;
-
-import java.nio.ByteBuffer;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.IllegalFormatException;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.LinkedBlockingQueue;
-
-/**
- * Manages logging for the entire module.
- */
-@VisibleForTesting
-public class Log {
-
-    public static final class Sessions {
-        public static final String ICA_ANSWER_CALL = "ICA.aC";
-        public static final String ICA_REJECT_CALL = "ICA.rC";
-        public static final String ICA_DISCONNECT_CALL = "ICA.dC";
-        public static final String ICA_HOLD_CALL = "ICA.hC";
-        public static final String ICA_UNHOLD_CALL = "ICA.uC";
-        public static final String ICA_MUTE = "ICA.m";
-        public static final String ICA_SET_AUDIO_ROUTE = "ICA.sAR";
-        public static final String ICA_CONFERENCE = "ICA.c";
-        public static final String CSW_HANDLE_CREATE_CONNECTION_COMPLETE = "CSW.hCCC";
-        public static final String CSW_SET_ACTIVE = "CSW.sA";
-        public static final String CSW_SET_RINGING = "CSW.sR";
-        public static final String CSW_SET_DIALING = "CSW.sD";
-        public static final String CSW_SET_PULLING = "CSW.sP";
-        public static final String CSW_SET_DISCONNECTED = "CSW.sDc";
-        public static final String CSW_SET_ON_HOLD = "CSW.sOH";
-        public static final String CSW_REMOVE_CALL = "CSW.rC";
-        public static final String CSW_SET_IS_CONFERENCED = "CSW.sIC";
-        public static final String CSW_ADD_CONFERENCE_CALL = "CSW.aCC";
-    }
-
-    /**
-     * Stores the various events associated with {@link Call}s. Also stores all request-response
-     * pairs amongst the events.
-     */
-    public final static class Events {
-        public static class TimedEventPair {
-            private static final long DEFAULT_TIMEOUT = 3000L;
-
-            String mRequest;
-            String mResponse;
-            String mName;
-            long mTimeoutMillis = DEFAULT_TIMEOUT;
-
-            public TimedEventPair(String request, String response,
-                    String name) {
-                this.mRequest = request;
-                this.mResponse = response;
-                this.mName = name;
-            }
-
-            public TimedEventPair(String request, String response,
-                    String name, long timeoutMillis) {
-                this.mRequest = request;
-                this.mResponse = response;
-                this.mName = name;
-                this.mTimeoutMillis = timeoutMillis;
-            }
-        }
-
-        public static final String CREATED = "CREATED";
-        public static final String DESTROYED = "DESTROYED";
-        public static final String SET_CONNECTING = "SET_CONNECTING";
-        public static final String SET_DIALING = "SET_DIALING";
-        public static final String SET_PULLING = "SET_PULLING";
-        public static final String SET_ACTIVE = "SET_ACTIVE";
-        public static final String SET_HOLD = "SET_HOLD";
-        public static final String SET_RINGING = "SET_RINGING";
-        public static final String SET_DISCONNECTED = "SET_DISCONNECTED";
-        public static final String SET_DISCONNECTING = "SET_DISCONNECTING";
-        public static final String SET_SELECT_PHONE_ACCOUNT = "SET_SELECT_PHONE_ACCOUNT";
-        public static final String REQUEST_HOLD = "REQUEST_HOLD";
-        public static final String REQUEST_UNHOLD = "REQUEST_UNHOLD";
-        public static final String REQUEST_DISCONNECT = "REQUEST_DISCONNECT";
-        public static final String REQUEST_ACCEPT = "REQUEST_ACCEPT";
-        public static final String REQUEST_REJECT = "REQUEST_REJECT";
-        public static final String START_DTMF = "START_DTMF";
-        public static final String STOP_DTMF = "STOP_DTMF";
-        public static final String START_RINGER = "START_RINGER";
-        public static final String STOP_RINGER = "STOP_RINGER";
-        public static final String SKIP_RINGING = "SKIP_RINGING";
-        public static final String START_CALL_WAITING_TONE = "START_CALL_WAITING_TONE";
-        public static final String STOP_CALL_WAITING_TONE = "STOP_CALL_WAITING_TONE";
-        public static final String START_CONNECTION = "START_CONNECTION";
-        public static final String BIND_CS = "BIND_CS";
-        public static final String CS_BOUND = "CS_BOUND";
-        public static final String CONFERENCE_WITH = "CONF_WITH";
-        public static final String SPLIT_FROM_CONFERENCE = "CONF_SPLIT";
-        public static final String SWAP = "SWAP";
-        public static final String ADD_CHILD = "ADD_CHILD";
-        public static final String REMOVE_CHILD = "REMOVE_CHILD";
-        public static final String SET_PARENT = "SET_PARENT";
-        public static final String MUTE = "MUTE";
-        public static final String UNMUTE = "UNMUTE";
-        public static final String AUDIO_ROUTE = "AUDIO_ROUTE";
-        public static final String AUDIO_ROUTE_EARPIECE = "AUDIO_ROUTE_EARPIECE";
-        public static final String AUDIO_ROUTE_HEADSET = "AUDIO_ROUTE_HEADSET";
-        public static final String AUDIO_ROUTE_BT = "AUDIO_ROUTE_BT";
-        public static final String AUDIO_ROUTE_SPEAKER = "AUDIO_ROUTE_SPEAKER";
-        public static final String ERROR_LOG = "ERROR";
-        public static final String USER_LOG_MARK = "USER_LOG_MARK";
-        public static final String SILENCE = "SILENCE";
-        public static final String BIND_SCREENING = "BIND_SCREENING";
-        public static final String SCREENING_BOUND = "SCREENING_BOUND";
-        public static final String SCREENING_SENT = "SCREENING_SENT";
-        public static final String SCREENING_COMPLETED = "SCREENING_COMPLETED";
-        public static final String BLOCK_CHECK_INITIATED = "BLOCK_CHECK_INITIATED";
-        public static final String BLOCK_CHECK_FINISHED = "BLOCK_CHECK_FINISHED";
-        public static final String DIRECT_TO_VM_INITIATED = "DIRECT_TO_VM_INITIATED";
-        public static final String DIRECT_TO_VM_FINISHED = "DIRECT_TO_VM_FINISHED";
-        public static final String FILTERING_INITIATED = "FILTERING_INITIATED";
-        public static final String FILTERING_COMPLETED = "FILTERING_COMPLETED";
-        public static final String FILTERING_TIMED_OUT = "FILTERING_TIMED_OUT";
-        public static final String REMOTELY_HELD = "REMOTELY_HELD";
-        public static final String REMOTELY_UNHELD = "REMOTELY_UNHELD";
-        public static final String REQUEST_PULL = "PULL";
-        public static final String INFO = "INFO";
-        public static final String VIDEO_STATE_CHANGED = "VIDEO_STATE_CHANGED";
-        public static final String RECEIVE_VIDEO_REQUEST = "RECEIVE_VIDEO_REQUEST";
-        public static final String RECEIVE_VIDEO_RESPONSE = "RECEIVE_VIDEO_RESPONSE";
-        public static final String SEND_VIDEO_REQUEST = "SEND_VIDEO_REQUEST";
-        public static final String SEND_VIDEO_RESPONSE = "SEND_VIDEO_RESPONSE";
-        public static final String IS_EXTERNAL = "IS_EXTERNAL";
-        public static final String PROPERTY_CHANGE = "PROPERTY_CHANGE";
-        public static final String CAPABILITY_CHANGE = "CAPABILITY_CHANGE";
-        public static final String CONNECTION_EVENT = "CONNECTION_EVENT";
-
-        public static class Timings {
-            public static final String ACCEPT_TIMING = "accept";
-            public static final String REJECT_TIMING = "reject";
-            public static final String DISCONNECT_TIMING = "disconnect";
-            public static final String HOLD_TIMING = "hold";
-            public static final String UNHOLD_TIMING = "unhold";
-            public static final String OUTGOING_TIME_TO_DIALING_TIMING = "outgoing_time_to_dialing";
-            public static final String BIND_CS_TIMING = "bind_cs";
-            public static final String SCREENING_COMPLETED_TIMING = "screening_completed";
-            public static final String DIRECT_TO_VM_FINISHED_TIMING = "direct_to_vm_finished";
-            public static final String BLOCK_CHECK_FINISHED_TIMING = "block_check_finished";
-            public static final String FILTERING_COMPLETED_TIMING = "filtering_completed";
-            public static final String FILTERING_TIMED_OUT_TIMING = "filtering_timed_out";
-
-            private static final TimedEventPair[] sTimedEvents = {
-                    new TimedEventPair(REQUEST_ACCEPT, SET_ACTIVE, ACCEPT_TIMING),
-                    new TimedEventPair(REQUEST_REJECT, SET_DISCONNECTED, REJECT_TIMING),
-                    new TimedEventPair(REQUEST_DISCONNECT, SET_DISCONNECTED, DISCONNECT_TIMING),
-                    new TimedEventPair(REQUEST_HOLD, SET_HOLD, HOLD_TIMING),
-                    new TimedEventPair(REQUEST_UNHOLD, SET_ACTIVE, UNHOLD_TIMING),
-                    new TimedEventPair(START_CONNECTION, SET_DIALING,
-                            OUTGOING_TIME_TO_DIALING_TIMING),
-                    new TimedEventPair(BIND_CS, CS_BOUND, BIND_CS_TIMING),
-                    new TimedEventPair(SCREENING_SENT, SCREENING_COMPLETED,
-                            SCREENING_COMPLETED_TIMING),
-                    new TimedEventPair(DIRECT_TO_VM_INITIATED, DIRECT_TO_VM_FINISHED,
-                            DIRECT_TO_VM_FINISHED_TIMING),
-                    new TimedEventPair(BLOCK_CHECK_INITIATED, BLOCK_CHECK_FINISHED,
-                            BLOCK_CHECK_FINISHED_TIMING),
-                    new TimedEventPair(FILTERING_INITIATED, FILTERING_COMPLETED,
-                            FILTERING_COMPLETED_TIMING),
-                    new TimedEventPair(FILTERING_INITIATED, FILTERING_TIMED_OUT,
-                            FILTERING_TIMED_OUT_TIMING, 6000L),
-            };
-        }
-
-        /**
-         * Maps from request events to a list of possible response events. Used to track
-         * end-to-end timing for critical user-facing operations in Telecom.
-         */
-        public static final Map<String, List<TimedEventPair>> requestResponsePairs;
-        static {
-            requestResponsePairs = new HashMap<>();
-            for (TimedEventPair p : Timings.sTimedEvents) {
-                if (requestResponsePairs.containsKey(p.mRequest)) {
-                    requestResponsePairs.get(p.mRequest).add(p);
-                } else {
-                    ArrayList<TimedEventPair> responses = new ArrayList<>();
-                    responses.add(p);
-                    requestResponsePairs.put(p.mRequest, responses);
-                }
-            }
-        }
-    }
-
-    public static class CallEvent {
-        public String eventId;
-        public String sessionId;
-        public long time;
-        public Object data;
-
-        public CallEvent(String eventId, String sessionId, long time, Object data) {
-            this.eventId = eventId;
-            this.sessionId = sessionId;
-            this.time = time;
-            this.data = data;
-        }
-    }
-
-    public static class CallEventRecord {
-        public static class EventTiming extends TimedEvent<String> {
-            public String name;
-            public long time;
-
-            public EventTiming(String name, long time) {
-                this.name = name;
-                this.time = time;
-            }
-
-            public String getKey() {
-                return name;
-            }
-
-            public long getTime() {
-                return time;
-            }
-        }
-
-        private static class PendingResponse {
-            String requestEventId;
-            long requestEventTimeMillis;
-            long timeoutMillis;
-            String name;
-
-            public PendingResponse(String requestEventId, long requestEventTimeMillis,
-                    long timeoutMillis, String name) {
-                this.requestEventId = requestEventId;
-                this.requestEventTimeMillis = requestEventTimeMillis;
-                this.timeoutMillis = timeoutMillis;
-                this.name = name;
-            }
-        }
-
-        private static final DateFormat sLongDateFormat = new SimpleDateFormat(
-                "yyyy-MM-dd HH:mm:ss.SSS");
-        private static final DateFormat sDateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
-        private final List<CallEvent> mEvents = new LinkedList<>();
-        private final Call mCall;
-
-        public CallEventRecord(Call call) {
-            mCall = call;
-        }
-
-        public Call getCall() {
-            return mCall;
-        }
-
-        public void addEvent(String event, String sessionId, Object data) {
-            mEvents.add(new CallEvent(event, sessionId, System.currentTimeMillis(), data));
-            Log.i("Event", "Call %s: %s, %s", mCall.getId(), event, data);
-        }
-
-        public List<CallEvent> getEvents() {
-            return mEvents;
-        }
-
-        public List<EventTiming> extractEventTimings() {
-            if (mEvents == null) {
-                return Collections.emptyList();
-            }
-
-            LinkedList<EventTiming> result = new LinkedList<>();
-            Map<String, PendingResponse> pendingResponses = new HashMap<>();
-            for (CallEvent event : mEvents) {
-                if (Events.requestResponsePairs.containsKey(event.eventId)) {
-                    // This event expects a response, so add that expected response to the maps
-                    // of pending events.
-                    for (Events.TimedEventPair p : Events.requestResponsePairs.get(event.eventId)) {
-                        pendingResponses.put(p.mResponse, new PendingResponse(event.eventId,
-                                event.time, p.mTimeoutMillis, p.mName));
-                    }
-                }
-
-                PendingResponse pendingResponse = pendingResponses.remove(event.eventId);
-                if (pendingResponse != null) {
-                    long elapsedTime = event.time - pendingResponse.requestEventTimeMillis;
-                    if (elapsedTime < pendingResponse.timeoutMillis) {
-                        result.add(new EventTiming(pendingResponse.name, elapsedTime));
-                    }
-                }
-            }
-
-            return result;
-        }
-
-        public void dump(IndentingPrintWriter pw) {
-            pw.print("Call ");
-            pw.print(mCall.getId());
-            pw.print(" [");
-            pw.print(sLongDateFormat.format(new Date(mCall.getCreationTimeMillis())));
-            pw.print("]");
-            pw.println(mCall.isIncoming() ? "(MT - incoming)" : "(MO - outgoing)");
-
-            pw.increaseIndent();
-            pw.println("To address: " + piiHandle(mCall.getHandle()));
-
-            for (CallEvent event : mEvents) {
-                pw.print(sDateFormat.format(new Date(event.time)));
-                pw.print(" - ");
-                pw.print(event.eventId);
-                if (event.data != null) {
-                    pw.print(" (");
-                    Object data = event.data;
-
-                    if (data instanceof Call) {
-                        // If the data is another call, then change the data to the call's CallEvent
-                        // ID instead.
-                        CallEventRecord record = mCallEventRecordMap.get(data);
-                        if (record != null) {
-                            data = "Call " + record.mCall.getId();
-                        }
-                    }
-
-                    pw.print(data);
-                    pw.print(")");
-                }
-                pw.print(":");
-                pw.print(event.sessionId);
-                pw.println();
-            }
-
-            pw.println("Timings (average for this call, milliseconds):");
-            pw.increaseIndent();
-            Map<String, Double> avgEventTimings = EventTiming.averageTimings(extractEventTimings());
-            List<String> eventNames = new ArrayList<>(avgEventTimings.keySet());
-            Collections.sort(eventNames);
-            for (String eventName : eventNames) {
-                pw.printf("%s: %.2f\n", eventName, avgEventTimings.get(eventName));
-            }
-            pw.decreaseIndent();
-            pw.decreaseIndent();
-        }
-    }
-
-    public static final int MAX_CALLS_TO_CACHE = 10;  // Arbitrarily chosen.
-    public static final int MAX_CALLS_TO_CACHE_DEBUG = 20;  // Arbitrarily chosen.
-    private static final long EXTENDED_LOGGING_DURATION_MILLIS = 60000 * 30; // 30 minutes
-
-    // Don't check in with this true!
-    private static final boolean LOG_DBG = false;
-
-    // Currently using 3 letters, So don't exceed 64^3
-    private static final long SESSION_ID_ROLLOVER_THRESHOLD = 262144;
-
-    // Generic tag for all In Call logging
-    @VisibleForTesting
-    public static String TAG = "Telecom";
-    public static String LOGGING_TAG = "Logging";
-
-    public static final boolean FORCE_LOGGING = false; /* STOP SHIP if true */
-    public static final boolean SYSTRACE_DEBUG = false; /* STOP SHIP if true */
-    public static final boolean DEBUG = isLoggable(android.util.Log.DEBUG);
-    public static final boolean INFO = isLoggable(android.util.Log.INFO);
-    public static final boolean VERBOSE = isLoggable(android.util.Log.VERBOSE);
-    public static final boolean WARN = isLoggable(android.util.Log.WARN);
-    public static final boolean ERROR = isLoggable(android.util.Log.ERROR);
-
-    private static final Map<Call, CallEventRecord> mCallEventRecordMap = new HashMap<>();
-    private static LinkedBlockingQueue<CallEventRecord> mCallEventRecords =
-            new LinkedBlockingQueue<CallEventRecord>(MAX_CALLS_TO_CACHE);
-
-    private static Context mContext = null;
-    // Synchronized in all method calls
-    private static int sCodeEntryCounter = 0;
-    @VisibleForTesting
-    public static ConcurrentHashMap<Integer, Session> sSessionMapper = new ConcurrentHashMap<>(100);
-    @VisibleForTesting
-    public static Handler sSessionCleanupHandler = new Handler(Looper.getMainLooper());
-    @VisibleForTesting
-    public static java.lang.Runnable sCleanStaleSessions = new java.lang.Runnable() {
-        @Override
-        public void run() {
-            cleanupStaleSessions(getSessionCleanupTimeoutMs());
-        }
-    };
-
-    // Set the logging container to be the system's. This will only change when being mocked
-    // during testing.
-    private static SystemLoggingContainer systemLogger = new SystemLoggingContainer();
-
-    /**
-     * Tracks whether user-activated extended logging is enabled.
-     */
-    private static boolean mIsUserExtendedLoggingEnabled = false;
-
-    /**
-     * The time when user-activated extended logging should be ended.  Used to determine when
-     * extended logging should automatically be disabled.
-     */
-    private static long mUserExtendedLoggingStopTime = 0;
-
-    private Log() {
-    }
-
-    public static void setContext(Context context) {
-        mContext = context;
-    }
-
-    /**
-     * Enable or disable extended telecom logging.
-     *
-     * @param isExtendedLoggingEnabled {@code true} if extended logging should be enabled,
-     *          {@code false} if it should be disabled.
-     */
-    public static void setIsExtendedLoggingEnabled(boolean isExtendedLoggingEnabled) {
-        // If the state hasn't changed, bail early.
-        if (mIsUserExtendedLoggingEnabled == isExtendedLoggingEnabled) {
-            return;
-        }
-
-        // Resize the event queue.
-        int newSize = isExtendedLoggingEnabled ? MAX_CALLS_TO_CACHE_DEBUG : MAX_CALLS_TO_CACHE;
-        LinkedBlockingQueue<CallEventRecord> oldEventLog = mCallEventRecords;
-        mCallEventRecords = new LinkedBlockingQueue<CallEventRecord>(newSize);
-        mCallEventRecordMap.clear();
-
-        // Copy the existing queue into the new one.
-        for (CallEventRecord event : oldEventLog) {
-            addCallEventRecord(event);
-        }
-
-        mIsUserExtendedLoggingEnabled = isExtendedLoggingEnabled;
-        if (mIsUserExtendedLoggingEnabled) {
-            mUserExtendedLoggingStopTime = System.currentTimeMillis()
-                    + EXTENDED_LOGGING_DURATION_MILLIS;
-        } else {
-            mUserExtendedLoggingStopTime = 0;
-        }
-    }
-
-    public static final long DEFAULT_SESSION_TIMEOUT_MS = 30000L; // 30 seconds
-    private static MessageDigest sMessageDigest;
-
-    public static void initMd5Sum() {
-        new AsyncTask<Void, Void, Void>() {
-            @Override
-            public Void doInBackground(Void... args) {
-                MessageDigest md;
-                try {
-                    md = MessageDigest.getInstance("SHA-1");
-                } catch (NoSuchAlgorithmException e) {
-                    md = null;
-                }
-                sMessageDigest = md;
-                return null;
-            }
-        }.execute();
-    }
-
-    @VisibleForTesting
-    public static void setTag(String tag) {
-        TAG = tag;
-    }
-
-    @VisibleForTesting
-    public static void setLoggingContainer(SystemLoggingContainer logger) {
-        systemLogger = logger;
-    }
-
-    // Overridden in LogTest to skip query to ContentProvider
-    public interface ISessionCleanupTimeoutMs {
-        long get();
-    }
-    @VisibleForTesting
-    public static ISessionCleanupTimeoutMs sSessionCleanupTimeoutMs =
-            new ISessionCleanupTimeoutMs() {
-                @Override
-                public long get() {
-                    // mContext will be null if Log is called from another process
-                    // (UserCallActivity, for example). For these cases, use the default value.
-                    if(mContext == null) {
-                        return DEFAULT_SESSION_TIMEOUT_MS;
-                    }
-                    return Timeouts.getStaleSessionCleanupTimeoutMillis(
-                            mContext.getContentResolver());
-                }
-            };
-
-    private static long getSessionCleanupTimeoutMs() {
-        return sSessionCleanupTimeoutMs.get();
-    }
-
-    private static synchronized void resetStaleSessionTimer() {
-        sSessionCleanupHandler.removeCallbacksAndMessages(null);
-        // Will be null in Log Testing
-        if (sCleanStaleSessions != null) {
-            sSessionCleanupHandler.postDelayed(sCleanStaleSessions, getSessionCleanupTimeoutMs());
-        }
-    }
-
-    /**
-     * Call at an entry point to the Telecom code to track the session. This code must be
-     * accompanied by a Log.endSession().
-     */
-    public static synchronized void startSession(String shortMethodName) {
-        startSession(shortMethodName, null);
-    }
-    public static synchronized void startSession(String shortMethodName,
-            String callerIdentification) {
-        resetStaleSessionTimer();
-        int threadId = getCallingThreadId();
-        Session activeSession = sSessionMapper.get(threadId);
-        // We have called startSession within an active session that has not ended... Register this
-        // session as a subsession.
-        if (activeSession != null) {
-            Session childSession = createSubsession(true);
-            continueSession(childSession, shortMethodName);
-            return;
-        }
-        Session newSession = new Session(getNextSessionID(), shortMethodName,
-                System.currentTimeMillis(), threadId, false, callerIdentification);
-        sSessionMapper.put(threadId, newSession);
-
-        Log.v(LOGGING_TAG, Session.START_SESSION);
-    }
-
-
-    /**
-     * Notifies the logging system that a subsession will be run at a later point and
-     * allocates the resources. Returns a session object that must be used in
-     * Log.continueSession(...) to start the subsession.
-     */
-    public static Session createSubsession() {
-        return createSubsession(false);
-    }
-
-    private static synchronized Session createSubsession(boolean isStartedFromActiveSession) {
-        int threadId = getCallingThreadId();
-        Session threadSession = sSessionMapper.get(threadId);
-        if (threadSession == null) {
-            Log.d(LOGGING_TAG, "Log.createSubsession was called with no session active.");
-            return null;
-        }
-        // Start execution time of the session will be overwritten in continueSession(...).
-        Session newSubsession = new Session(threadSession.getNextChildId(),
-                threadSession.getShortMethodName(), System.currentTimeMillis(), threadId,
-                isStartedFromActiveSession, null);
-        threadSession.addChild(newSubsession);
-        newSubsession.setParentSession(threadSession);
-
-        if(!isStartedFromActiveSession) {
-            Log.v(LOGGING_TAG, Session.CREATE_SUBSESSION + " " + newSubsession.toString());
-        } else {
-            Log.v(LOGGING_TAG, Session.CREATE_SUBSESSION + " (Invisible subsession)");
-        }
-        return newSubsession;
-    }
-
-    /**
-     * Cancels a subsession that had Log.createSubsession() called on it, but will never have
-     * Log.continueSession(...) called on it due to an error. Allows the subsession to be cleaned
-     * gracefully instead of being removed by the mSessionCleanupHandler forcefully later.
-     */
-    public static synchronized void cancelSubsession(Session subsession) {
-        if (subsession == null) {
-            return;
-        }
-
-        subsession.markSessionCompleted(0);
-        endParentSessions(subsession);
-    }
-
-    /**
-     * Starts the subsession that was created in Log.CreateSubsession. The Log.endSession() method
-     * must be called at the end of this method. The full session will complete when all
-     * subsessions are completed.
-     */
-    public static synchronized void continueSession(Session subsession, String shortMethodName) {
-        if (subsession == null) {
-            return;
-        }
-        resetStaleSessionTimer();
-        String callingMethodName = subsession.getShortMethodName();
-        subsession.setShortMethodName(callingMethodName + "->" + shortMethodName);
-        subsession.setExecutionStartTimeMs(System.currentTimeMillis());
-        Session parentSession = subsession.getParentSession();
-        if (parentSession == null) {
-            Log.d(LOGGING_TAG, "Log.continueSession was called with no session active for " +
-                    "method %s.", shortMethodName);
-            return;
-        }
-
-        sSessionMapper.put(getCallingThreadId(), subsession);
-        if(!subsession.isStartedFromActiveSession()) {
-            Log.v(LOGGING_TAG, Session.CONTINUE_SUBSESSION);
-        } else {
-            Log.v(LOGGING_TAG, Session.CONTINUE_SUBSESSION + " (Invisible Subsession) with " +
-                    "Method " + shortMethodName);
-        }
-    }
-
-    public static void checkIsThreadLogged() {
-        int threadId = getCallingThreadId();
-        Session threadSession = sSessionMapper.get(threadId);
-        if (threadSession == null) {
-            android.util.Log.e(LOGGING_TAG, "Logging Thread Check Failed!", new Exception());
-        }
-    }
-
-    /**
-     * Ends the current session/subsession. Must be called after a Log.startSession(...) and
-     * Log.continueSession(...) call.
-     */
-    public static synchronized void endSession() {
-        int threadId = getCallingThreadId();
-        Session completedSession = sSessionMapper.get(threadId);
-        if (completedSession == null) {
-            Log.w(LOGGING_TAG, "Log.endSession was called with no session active.");
-            return;
-        }
-
-        completedSession.markSessionCompleted(System.currentTimeMillis());
-        if(!completedSession.isStartedFromActiveSession()) {
-            Log.v(LOGGING_TAG, Session.END_SUBSESSION + " (dur: " +
-                    completedSession.getLocalExecutionTime() + " mS)");
-        } else {
-            Log.v(LOGGING_TAG, Session.END_SUBSESSION + " (Invisible Subsession) (dur: " +
-                    completedSession.getLocalExecutionTime() + " mS)");
-        }
-        // Remove after completed so that reference still exists for logging the end events
-        Session parentSession = completedSession.getParentSession();
-        sSessionMapper.remove(threadId);
-        endParentSessions(completedSession);
-        // If this subsession was started from a parent session using Log.startSession, return the
-        // ThreadID back to the parent after completion.
-        if (parentSession != null && !parentSession.isSessionCompleted() &&
-                completedSession.isStartedFromActiveSession()) {
-            sSessionMapper.put(threadId, parentSession);
-        }
-    }
-
-    // Recursively deletes all complete parent sessions of the current subsession if it is a leaf.
-    private static void endParentSessions(Session subsession) {
-        // Session is not completed or not currently a leaf, so we can not remove because a child is
-        // still running
-        if (!subsession.isSessionCompleted() || subsession.getChildSessions().size() != 0) {
-            return;
-        }
-
-        Session parentSession = subsession.getParentSession();
-        if (parentSession != null) {
-            subsession.setParentSession(null);
-            parentSession.removeChild(subsession);
-            endParentSessions(parentSession);
-        } else {
-            // All of the subsessions have been completed and it is time to report on the full
-            // running time of the session.
-            long fullSessionTimeMs =
-                    System.currentTimeMillis() - subsession.getExecutionStartTimeMilliseconds();
-            Analytics.addSessionTiming(subsession.getShortMethodName(), fullSessionTimeMs);
-            Log.v(LOGGING_TAG, Session.END_SESSION + " (dur: " + fullSessionTimeMs + " ms): " +
-                    subsession.toString());
-        }
-    }
-
-    private synchronized static String getNextSessionID() {
-        Integer nextId = sCodeEntryCounter++;
-        if (nextId >= SESSION_ID_ROLLOVER_THRESHOLD) {
-            restartSessionCounter();
-            nextId = sCodeEntryCounter++;
-        }
-        return getBase64Encoding(nextId);
-    }
-
-    @VisibleForTesting
-    public synchronized static void restartSessionCounter() {
-        sCodeEntryCounter = 0;
-    }
-
-    @VisibleForTesting
-    public static String getBase64Encoding(int number) {
-        byte[] idByteArray = ByteBuffer.allocate(4).putInt(number).array();
-        idByteArray = Arrays.copyOfRange(idByteArray, 2, 4);
-        return Base64.encodeToString(idByteArray, Base64.NO_WRAP | Base64.NO_PADDING);
-    }
-
-    public static int getCallingThreadId() {
-        return android.os.Process.myTid();
-    }
-
-    public static void event(Call call, String event) {
-        event(call, event, null);
-    }
-
-    public static void event(Call call, String event, Object data) {
-        Session currentSession = sSessionMapper.get(getCallingThreadId());
-        String currentSessionID = currentSession != null ? currentSession.toString() : "";
-
-        if (call == null) {
-            Log.i(TAG, "Non-call EVENT: %s, %s", event, data);
-            return;
-        }
-        synchronized (mCallEventRecords) {
-            if (!mCallEventRecordMap.containsKey(call)) {
-                CallEventRecord newRecord = new CallEventRecord(call);
-                addCallEventRecord(newRecord);
-            }
-
-            CallEventRecord record = mCallEventRecordMap.get(call);
-            record.addEvent(event, currentSessionID, data);
-        }
-    }
-
-    public static void event(Call call, String event, String format, Object... args) {
-        String msg;
-        try {
-            msg = (args == null || args.length == 0) ? format
-                    : String.format(Locale.US, format, args);
-        } catch (IllegalFormatException ife) {
-            e("Log", ife, "IllegalFormatException: formatString='%s' numArgs=%d", format,
-                    args.length);
-            msg = format + " (An error occurred while formatting the message.)";
-        }
-
-        event(call, event, msg);
-    }
-
-    @VisibleForTesting
-    public static synchronized void cleanupStaleSessions(long timeoutMs) {
-        String logMessage = "Stale Sessions Cleaned:\n";
-        boolean isSessionsStale = false;
-        long currentTimeMs = System.currentTimeMillis();
-        // Remove references that are in the Session Mapper (causing GC to occur) on
-        // sessions that are lasting longer than LOGGING_SESSION_TIMEOUT_MS.
-        // If this occurs, then there is most likely a Session active that never had
-        // Log.endSession called on it.
-        for (Iterator<ConcurrentHashMap.Entry<Integer, Session>> it =
-             sSessionMapper.entrySet().iterator(); it.hasNext(); ) {
-            ConcurrentHashMap.Entry<Integer, Session> entry = it.next();
-            Session session = entry.getValue();
-            if (currentTimeMs - session.getExecutionStartTimeMilliseconds() > timeoutMs) {
-                it.remove();
-                logMessage += session.printFullSessionTree() + "\n";
-                isSessionsStale = true;
-            }
-        }
-        if (isSessionsStale) {
-            Log.w(LOGGING_TAG, logMessage);
-        } else {
-            Log.v(LOGGING_TAG, "No stale logging sessions needed to be cleaned...");
-        }
-    }
-
-    private static void addCallEventRecord(CallEventRecord newRecord) {
-        Call call = newRecord.getCall();
-
-        // First remove the oldest entry if no new ones exist.
-        if (mCallEventRecords.remainingCapacity() == 0) {
-            CallEventRecord record = mCallEventRecords.poll();
-            if (record != null) {
-                mCallEventRecordMap.remove(record.getCall());
-            }
-        }
-
-        // Now add a new entry
-        mCallEventRecords.add(newRecord);
-        mCallEventRecordMap.put(call, newRecord);
-
-        // Register the events with Analytics
-        if (call.getAnalytics() != null) {
-            call.getAnalytics().setCallEvents(newRecord);
-        } else {
-            Log.w(LOGGING_TAG, "Call analytics is null");
-        }
-    }
-
-    /**
-     * If user enabled extended logging is enabled and the time limit has passed, disables the
-     * extended logging.
-     */
-    private static void maybeDisableLogging() {
-        if (!mIsUserExtendedLoggingEnabled) {
-            return;
-        }
-
-        if (mUserExtendedLoggingStopTime < System.currentTimeMillis()) {
-            mUserExtendedLoggingStopTime = 0;
-            mIsUserExtendedLoggingEnabled = false;
-        }
-    }
-
-    public static boolean isLoggable(int level) {
-        return FORCE_LOGGING || android.util.Log.isLoggable(TAG, level);
-    }
-
-    public static void d(String prefix, String format, Object... args) {
-        if (mIsUserExtendedLoggingEnabled) {
-            maybeDisableLogging();
-            systemLogger.i(TAG, buildMessage(prefix, format, args));
-        } else if (DEBUG) {
-            systemLogger.d(TAG, buildMessage(prefix, format, args));
-        }
-    }
-
-    public static void d(Object objectPrefix, String format, Object... args) {
-        if (mIsUserExtendedLoggingEnabled) {
-            maybeDisableLogging();
-            systemLogger.i(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
-        } else if (DEBUG) {
-            systemLogger.d(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
-        }
-    }
-
-    public static void i(String prefix, String format, Object... args) {
-        if (INFO) {
-            systemLogger.i(TAG, buildMessage(prefix, format, args));
-        }
-    }
-
-    public static void i(Object objectPrefix, String format, Object... args) {
-        if (INFO) {
-            systemLogger.i(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
-        }
-    }
-
-    public static void v(String prefix, String format, Object... args) {
-        if (mIsUserExtendedLoggingEnabled) {
-            maybeDisableLogging();
-            systemLogger.i(TAG, buildMessage(prefix, format, args));
-        } else if (VERBOSE) {
-            systemLogger.v(TAG, buildMessage(prefix, format, args));
-        }
-    }
-
-    public static void v(Object objectPrefix, String format, Object... args) {
-        if (mIsUserExtendedLoggingEnabled) {
-            maybeDisableLogging();
-            systemLogger.i(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
-        } else if (VERBOSE) {
-            systemLogger.v(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
-        }
-    }
-
-    public static void w(String prefix, String format, Object... args) {
-        if (WARN) {
-            systemLogger.w(TAG, buildMessage(prefix, format, args));
-        }
-    }
-
-    public static void w(Object objectPrefix, String format, Object... args) {
-        if (WARN) {
-            systemLogger.w(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
-        }
-    }
-
-    public static void e(String prefix, Throwable tr, String format, Object... args) {
-        if (ERROR) {
-            systemLogger.e(TAG, buildMessage(prefix, format, args), tr);
-        }
-    }
-
-    public static void e(Object objectPrefix, Throwable tr, String format, Object... args) {
-        if (ERROR) {
-            systemLogger.e(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args),
-                    tr);
-        }
-    }
-
-    public static void wtf(String prefix, Throwable tr, String format, Object... args) {
-        systemLogger.wtf(TAG, buildMessage(prefix, format, args), tr);
-    }
-
-    public static void wtf(Object objectPrefix, Throwable tr, String format, Object... args) {
-        systemLogger.wtf(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args),
-                tr);
-    }
-
-    public static void wtf(String prefix, String format, Object... args) {
-        String msg = buildMessage(prefix, format, args);
-        systemLogger.wtf(TAG, msg, new IllegalStateException(msg));
-    }
-
-    public static void wtf(Object objectPrefix, String format, Object... args) {
-        String msg = buildMessage(getPrefixFromObject(objectPrefix), format, args);
-        systemLogger.wtf(TAG, msg, new IllegalStateException(msg));
-    }
-
-    public static String piiHandle(Object pii) {
-        if (pii == null || VERBOSE) {
-            return String.valueOf(pii);
-        }
-
-        StringBuilder sb = new StringBuilder();
-        if (pii instanceof Uri) {
-            Uri uri = (Uri) pii;
-            String scheme = uri.getScheme();
-
-            if (!TextUtils.isEmpty(scheme)) {
-                sb.append(scheme).append(":");
-            }
-
-            String textToObfuscate = uri.getSchemeSpecificPart();
-            if (PhoneAccount.SCHEME_TEL.equals(scheme)) {
-                for (int i = 0; i < textToObfuscate.length(); i++) {
-                    char c = textToObfuscate.charAt(i);
-                    sb.append(PhoneNumberUtils.isDialable(c) ? "*" : c);
-                }
-            } else if (PhoneAccount.SCHEME_SIP.equals(scheme)) {
-                for (int i = 0; i < textToObfuscate.length(); i++) {
-                    char c = textToObfuscate.charAt(i);
-                    if (c != '@' && c != '.') {
-                        c = '*';
-                    }
-                    sb.append(c);
-                }
-            } else {
-                sb.append(pii(pii));
-            }
-        }
-
-        return sb.toString();
-    }
-
-    /**
-     * Redact personally identifiable information for production users.
-     * If we are running in verbose mode, return the original string, otherwise
-     * return a SHA-1 hash of the input string.
-     */
-    public static String pii(Object pii) {
-        if (pii == null || VERBOSE) {
-            return String.valueOf(pii);
-        }
-        return "[" + secureHash(String.valueOf(pii).getBytes()) + "]";
-    }
-
-    public static void dumpCallEvents(IndentingPrintWriter pw) {
-        pw.println("Historical Calls:");
-        pw.increaseIndent();
-        for (CallEventRecord callEventRecord : mCallEventRecords) {
-            callEventRecord.dump(pw);
-        }
-        pw.decreaseIndent();
-    }
-
-    private static String secureHash(byte[] input) {
-        if (sMessageDigest != null) {
-            sMessageDigest.reset();
-            sMessageDigest.update(input);
-            byte[] result = sMessageDigest.digest();
-            return encodeHex(result);
-        } else {
-            return "Uninitialized SHA1";
-        }
-    }
-
-    private static String encodeHex(byte[] bytes) {
-        StringBuffer hex = new StringBuffer(bytes.length * 2);
-
-        for (int i = 0; i < bytes.length; i++) {
-            int byteIntValue = bytes[i] & 0xff;
-            if (byteIntValue < 0x10) {
-                hex.append("0");
-            }
-            hex.append(Integer.toString(byteIntValue, 16));
-        }
-
-        return hex.toString();
-    }
-
-    private static String getPrefixFromObject(Object obj) {
-        return obj == null ? "<null>" : obj.getClass().getSimpleName();
-    }
-
-    private static String buildMessage(String prefix, String format, Object... args) {
-        if (LOG_DBG) {
-            checkIsThreadLogged();
-        }
-        // Incorporate thread ID and calling method into prefix
-        String sessionPostfix = "";
-        Session currentSession = sSessionMapper.get(getCallingThreadId());
-        if (currentSession != null) {
-            sessionPostfix = ": " + currentSession.toString();
-        }
-
-        String msg;
-        try {
-            msg = (args == null || args.length == 0) ? format
-                    : String.format(Locale.US, format, args);
-        } catch (IllegalFormatException ife) {
-            e("Log", ife, "IllegalFormatException: formatString='%s' numArgs=%d", format,
-                    args.length);
-            msg = format + " (An error occurred while formatting the message.)";
-        }
-        return String.format(Locale.US, "%s: %s%s", prefix, msg, sessionPostfix);
-    }
-}
diff --git a/src/com/android/server/telecom/LogUtils.java b/src/com/android/server/telecom/LogUtils.java
index 405e502..457db50 100644
--- a/src/com/android/server/telecom/LogUtils.java
+++ b/src/com/android/server/telecom/LogUtils.java
@@ -16,6 +16,7 @@
 
 package com.android.server.telecom;
 
+import android.content.Context;
 import android.telecom.Logging.EventManager;
 import android.telecom.Logging.EventManager.TimedEventPair;
 
@@ -27,6 +28,8 @@
 
     private static final String TAG = "Telecom";
 
+    public static final boolean SYSTRACE_DEBUG = false; /* STOP SHIP if true */
+
     public static final class Sessions {
         public static final String ICA_ANSWER_CALL = "ICA.aC";
         public static final String ICA_REJECT_CALL = "ICA.rC";
@@ -153,12 +156,10 @@
         }
     }
 
-    static {
-        initLogging();
-    }
-
-    private static void initLogging() {
+    public static void initLogging(Context context) {
         android.telecom.Log.setTag(TAG);
+        android.telecom.Log.setSessionContext(context);
+        android.telecom.Log.initMd5Sum();
         for (EventManager.TimedEventPair p : Events.Timings.sTimedEvents) {
             android.telecom.Log.addRequestResponsePair(p);
         }
diff --git a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
index 8b5604b..95ab7db 100644
--- a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
+++ b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
@@ -27,6 +27,7 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.telecom.GatewayInfo;
+import android.telecom.Log;
 import android.telecom.PhoneAccount;
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index 41eb9e4..143ea53 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -37,6 +37,7 @@
 import android.provider.Settings;
 import android.telecom.ConnectionService;
 import android.telecom.DefaultDialerManager;
+import android.telecom.Log;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telephony.CarrierConfigManager;
diff --git a/src/com/android/server/telecom/PhoneStateBroadcaster.java b/src/com/android/server/telecom/PhoneStateBroadcaster.java
index 0781ca2..a44fc03 100644
--- a/src/com/android/server/telecom/PhoneStateBroadcaster.java
+++ b/src/com/android/server/telecom/PhoneStateBroadcaster.java
@@ -18,6 +18,7 @@
 
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.telecom.Log;
 import android.telephony.TelephonyManager;
 
 import com.android.internal.telephony.ITelephonyRegistry;
diff --git a/src/com/android/server/telecom/ProximitySensorManager.java b/src/com/android/server/telecom/ProximitySensorManager.java
index e53b1d5..a79c0ed 100644
--- a/src/com/android/server/telecom/ProximitySensorManager.java
+++ b/src/com/android/server/telecom/ProximitySensorManager.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.os.PowerManager;
+import android.telecom.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 
diff --git a/src/com/android/server/telecom/QuickResponseUtils.java b/src/com/android/server/telecom/QuickResponseUtils.java
index fd0dbd2..5f8269d 100644
--- a/src/com/android/server/telecom/QuickResponseUtils.java
+++ b/src/com/android/server/telecom/QuickResponseUtils.java
@@ -20,6 +20,7 @@
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
+import android.telecom.Log;
 
 // TODO: Needed for move to system service: import com.android.internal.R;
 
diff --git a/src/com/android/server/telecom/RespondViaSmsManager.java b/src/com/android/server/telecom/RespondViaSmsManager.java
index 7609b08..6b2a39e 100644
--- a/src/com/android/server/telecom/RespondViaSmsManager.java
+++ b/src/com/android/server/telecom/RespondViaSmsManager.java
@@ -31,6 +31,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.telecom.Connection;
+import android.telecom.Log;
 import android.telecom.Response;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.SubscriptionManager;
diff --git a/src/com/android/server/telecom/RespondViaSmsSettings.java b/src/com/android/server/telecom/RespondViaSmsSettings.java
index f8aa568..2ea204a 100644
--- a/src/com/android/server/telecom/RespondViaSmsSettings.java
+++ b/src/com/android/server/telecom/RespondViaSmsSettings.java
@@ -20,6 +20,7 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.telecom.Log;
 import android.os.Bundle;
 import android.preference.EditTextPreference;
 import android.preference.Preference;
diff --git a/src/com/android/server/telecom/RingbackPlayer.java b/src/com/android/server/telecom/RingbackPlayer.java
index bfaf8a2..47b6dfe 100644
--- a/src/com/android/server/telecom/RingbackPlayer.java
+++ b/src/com/android/server/telecom/RingbackPlayer.java
@@ -17,6 +17,7 @@
 package com.android.server.telecom;
 
 import com.android.internal.util.Preconditions;
+import android.telecom.Log;
 
 /**
  * Plays ringback tones. Ringback is different from other tones because it operates as the current
diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java
index 262f437..a5bcca0 100644
--- a/src/com/android/server/telecom/Ringer.java
+++ b/src/com/android/server/telecom/Ringer.java
@@ -19,6 +19,7 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.content.Context;
+import android.telecom.Log;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.net.Uri;
@@ -109,7 +110,7 @@
         }
 
         if (mInCallController.doesConnectedDialerSupportRinging()) {
-            Log.event(foregroundCall, Log.Events.SKIP_RINGING);
+            Log.addEvent(foregroundCall, LogUtils.Events.SKIP_RINGING);
             return isRingerAudible;
         }
 
@@ -121,7 +122,7 @@
 
         if (isRingerAudible) {
             mRingingCall = foregroundCall;
-            Log.event(foregroundCall, Log.Events.START_RINGER);
+            Log.addEvent(foregroundCall, LogUtils.Events.START_RINGER);
             // Because we wait until a contact info query to complete before processing a
             // call (for the purposes of direct-to-voicemail), the information about custom
             // ringtones should be available by the time this code executes. We can safely
@@ -146,7 +147,7 @@
         }
 
         if (mInCallController.doesConnectedDialerSupportRinging()) {
-            Log.event(call, Log.Events.SKIP_RINGING);
+            Log.addEvent(call, LogUtils.Events.SKIP_RINGING);
             return;
         }
 
@@ -155,7 +156,7 @@
         stopRinging();
 
         if (mCallWaitingPlayer == null) {
-            Log.event(call, Log.Events.START_CALL_WAITING_TONE);
+            Log.addEvent(call, LogUtils.Events.START_CALL_WAITING_TONE);
             mCallWaitingCall = call;
             mCallWaitingPlayer =
                     mPlayerFactory.createPlayer(InCallTonePlayer.TONE_CALL_WAITING);
@@ -165,7 +166,7 @@
 
     public void stopRinging() {
         if (mRingingCall != null) {
-            Log.event(mRingingCall, Log.Events.STOP_RINGER);
+            Log.addEvent(mRingingCall, LogUtils.Events.STOP_RINGER);
             mRingingCall = null;
         }
 
@@ -181,7 +182,7 @@
         Log.v(this, "stop call waiting.");
         if (mCallWaitingPlayer != null) {
             if (mCallWaitingCall != null) {
-                Log.event(mCallWaitingCall, Log.Events.STOP_CALL_WAITING_TONE);
+                Log.addEvent(mCallWaitingCall, LogUtils.Events.STOP_CALL_WAITING_TONE);
                 mCallWaitingCall = null;
             }
 
diff --git a/src/com/android/server/telecom/RingtoneFactory.java b/src/com/android/server/telecom/RingtoneFactory.java
index 202efa9..7429775 100644
--- a/src/com/android/server/telecom/RingtoneFactory.java
+++ b/src/com/android/server/telecom/RingtoneFactory.java
@@ -26,6 +26,8 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+
+import android.telecom.Log;
 import android.telecom.PhoneAccount;
 import android.text.TextUtils;
 
diff --git a/src/com/android/server/telecom/Runnable.java b/src/com/android/server/telecom/Runnable.java
deleted file mode 100644
index c7ace72..0000000
--- a/src/com/android/server/telecom/Runnable.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.telecom;
-
-/**
- * Encapsulates session logging in a Runnable to reduce code duplication when continuing subsessions
- * in a handler/thread.
- */
-public abstract class Runnable {
-
-    private Session mSubsession;
-    private final String mSubsessionName;
-    private final Object mLock;
-    private final java.lang.Runnable mRunnable = new java.lang.Runnable() {
-            @Override
-            public void run() {
-                synchronized (mLock) {
-                    try {
-                        Log.continueSession(mSubsession, mSubsessionName);
-                        loggedRun();
-                    } finally {
-                        if (mSubsession != null) {
-                            Log.endSession();
-                            mSubsession = null;
-                        }
-                    }
-                }
-            }
-        };
-
-    /**
-     * Creates a new Telecom Runnable that incorporates Session Logging into it. Useful for carrying
-     * Logging Sessions through different threads as well as through handlers.
-     * @param subsessionName The name that will be used in the Logs to mark this Session
-     * @param lock The synchronization lock that will be used to lock loggedRun().
-     */
-    public Runnable(String subsessionName, Object lock) {
-        if (lock == null) {
-            mLock = new Object();
-        } else {
-            mLock = lock;
-        }
-        mSubsessionName = subsessionName;
-    }
-
-    /**
-     * Return the runnable that will be canceled in the handler queue.
-     * @return Runnable object to cancel.
-     */
-    public final java.lang.Runnable getRunnableToCancel() {
-        return mRunnable;
-    }
-
-    /**
-     * Creates a Runnable and a logging subsession that can be used in a handler/thread. Be sure to
-     * call cancel() if this session is never going to be run (removed from a handler queue, for
-     * for example).
-     * @return A Java Runnable that can be used in a handler queue or thread.
-     */
-    public java.lang.Runnable prepare() {
-        cancel();
-        mSubsession = Log.createSubsession();
-        return mRunnable;
-    }
-
-    /**
-     * This method is used to clean up the active session if the Runnable gets removed from a
-     * handler and is never run.
-     */
-    public void cancel() {
-        synchronized (mLock) {
-            Log.cancelSubsession(mSubsession);
-            mSubsession = null;
-        }
-    }
-
-    /**
-     * The method that will be run in the handler/thread. This method will be called with mLock
-     * held.
-     */
-    abstract public void loggedRun();
-
-}
diff --git a/src/com/android/server/telecom/ServiceBinder.java b/src/com/android/server/telecom/ServiceBinder.java
index 9a0f7b4..c86b5af 100644
--- a/src/com/android/server/telecom/ServiceBinder.java
+++ b/src/com/android/server/telecom/ServiceBinder.java
@@ -22,6 +22,7 @@
 import android.content.ServiceConnection;
 import android.os.IBinder;
 import android.os.UserHandle;
+import android.telecom.Log;
 import android.text.TextUtils;
 import android.util.ArraySet;
 
@@ -82,7 +83,7 @@
                 Intent serviceIntent = new Intent(mServiceAction).setComponent(mComponentName);
                 ServiceConnection connection = new ServiceBinderConnection(call);
 
-                Log.event(call, Log.Events.BIND_CS, mComponentName);
+                Log.addEvent(call, LogUtils.Events.BIND_CS, mComponentName);
                 final int bindingFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
                 final boolean isBound;
                 if (mUserHandle != null) {
@@ -120,7 +121,7 @@
                 synchronized (mLock) {
                     Log.i(this, "Service bound %s", componentName);
 
-                    Log.event(mCall, Log.Events.CS_BOUND, componentName);
+                    Log.addEvent(mCall, LogUtils.Events.CS_BOUND, componentName);
                     mCall = null;
 
                     // Unbind request was queued so unbind immediately.
diff --git a/src/com/android/server/telecom/Session.java b/src/com/android/server/telecom/Session.java
deleted file mode 100644
index 51ef0fa..0000000
--- a/src/com/android/server/telecom/Session.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.telecom;
-
-import android.annotation.NonNull;
-
-import java.util.ArrayList;
-
-/**
- * The session that stores information about a thread's point of entry into the Telecom code that
- * persists until the thread exits Telecom.
- */
-public class Session {
-
-    public static final String START_SESSION = "START_SESSION";
-    public static final String CREATE_SUBSESSION = "CREATE_SUBSESSION";
-    public static final String CONTINUE_SUBSESSION = "CONTINUE_SUBSESSION";
-    public static final String END_SUBSESSION = "END_SUBSESSION";
-    public static final String END_SESSION = "END_SESSION";
-
-    public static final int UNDEFINED = -1;
-
-    private String mSessionId;
-    private String mShortMethodName;
-    private long mExecutionStartTimeMs;
-    private long mExecutionEndTimeMs = UNDEFINED;
-    private Session mParentSession;
-    private ArrayList<Session> mChildSessions;
-    private boolean mIsCompleted = false;
-    private int mChildCounter = 0;
-    // True if this is a subsession that has been started from the same thread as the parent
-    // session. This can happen if Log.startSession(...) is called multiple times on the same
-    // thread in the case of one Telecom entry point method calling another entry point method.
-    // In this case, we can just make this subsession "invisible," but still keep track of it so
-    // that the Log.endSession() calls match up.
-    private boolean mIsStartedFromActiveSession = false;
-    // Optionally provided info about the method/class/component that started the session in order
-    // to make Logging easier. This info will be provided in parentheses along with the session.
-    private String mOwnerInfo;
-
-    public Session(String sessionId, String shortMethodName, long startTimeMs, long threadID,
-            boolean isStartedFromActiveSession, String ownerInfo) {
-        setSessionId(sessionId);
-        setShortMethodName(shortMethodName);
-        mExecutionStartTimeMs = startTimeMs;
-        mParentSession = null;
-        mChildSessions = new ArrayList<>(5);
-        mIsStartedFromActiveSession = isStartedFromActiveSession;
-        mOwnerInfo = ownerInfo;
-    }
-
-    public void setSessionId(@NonNull String sessionId) {
-       if(sessionId == null) {
-           mSessionId = "?";
-       }
-       mSessionId = sessionId;
-    }
-
-    public String getShortMethodName() {
-        return mShortMethodName;
-    }
-
-    public void setShortMethodName(String shortMethodName) {
-        if(shortMethodName == null) {
-            shortMethodName = "";
-        }
-        mShortMethodName = shortMethodName;
-    }
-
-    public void setParentSession(Session parentSession) {
-        mParentSession = parentSession;
-    }
-
-    public void addChild(Session childSession) {
-        if(childSession != null) {
-            mChildSessions.add(childSession);
-        }
-    }
-
-    public void removeChild(Session child) {
-        if(child != null) {
-            mChildSessions.remove(child);
-        }
-    }
-
-    public long getExecutionStartTimeMilliseconds() {
-        return mExecutionStartTimeMs;
-    }
-
-    public void setExecutionStartTimeMs(long startTimeMs) {
-        mExecutionStartTimeMs = startTimeMs;
-    }
-
-    public Session getParentSession() {
-        return mParentSession;
-    }
-
-    public ArrayList<Session> getChildSessions() {
-        return mChildSessions;
-    }
-
-    public boolean isSessionCompleted() {
-        return mIsCompleted;
-    }
-
-    public boolean isStartedFromActiveSession() {
-        return mIsStartedFromActiveSession;
-    }
-
-    // Mark this session complete. This will be deleted by Log when all subsessions are complete
-    // as well.
-    public void markSessionCompleted(long executionEndTimeMs) {
-        mExecutionEndTimeMs = executionEndTimeMs;
-        mIsCompleted = true;
-    }
-
-    public long getLocalExecutionTime() {
-        if(mExecutionEndTimeMs == UNDEFINED) {
-            return UNDEFINED;
-        }
-        return mExecutionEndTimeMs - mExecutionStartTimeMs;
-    }
-
-    public synchronized String getNextChildId() {
-        return String.valueOf(mChildCounter++);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof Session)) {
-            return false;
-        }
-        if (obj == this) {
-            return true;
-        }
-        Session otherSession = (Session) obj;
-        return (mSessionId.equals(otherSession.mSessionId)) &&
-                (mShortMethodName.equals(otherSession.mShortMethodName)) &&
-                mExecutionStartTimeMs == otherSession.mExecutionStartTimeMs &&
-                mParentSession == otherSession.mParentSession &&
-                mChildSessions.equals(otherSession.mChildSessions) &&
-                mIsCompleted == otherSession.mIsCompleted &&
-                mExecutionEndTimeMs == otherSession.mExecutionEndTimeMs &&
-                mChildCounter == otherSession.mChildCounter &&
-                mIsStartedFromActiveSession == otherSession.mIsStartedFromActiveSession &&
-                mOwnerInfo == otherSession.mOwnerInfo;
-    }
-
-    // Builds full session id recursively
-    private String getFullSessionId() {
-        // Cache mParentSession locally to prevent a concurrency problem where
-        // Log.endParentSessions() is called while a logging statement is running (Log.i, for
-        // example) and setting mParentSession to null in a different thread after the null check
-        // occurred.
-        Session parentSession = mParentSession;
-        if(parentSession == null) {
-            return mSessionId;
-        } else {
-            return parentSession.getFullSessionId() + "_" + mSessionId;
-        }
-    }
-
-    // Print out the full Session tree from any subsession node
-    public String printFullSessionTree() {
-        // Get to the top of the tree
-        Session topNode = this;
-        while(topNode.getParentSession() != null) {
-            topNode = topNode.getParentSession();
-        }
-        return topNode.printSessionTree();
-    }
-
-    // Recursively move down session tree using DFS, but print out each node when it is reached.
-    public String printSessionTree() {
-        StringBuilder sb = new StringBuilder();
-        printSessionTree(0, sb);
-        return sb.toString();
-    }
-
-    private void printSessionTree(int tabI, StringBuilder sb) {
-        sb.append(toString());
-        for (Session child : mChildSessions) {
-            sb.append("\n");
-            for(int i = 0; i <= tabI; i++) {
-                sb.append("\t");
-            }
-            child.printSessionTree(tabI + 1, sb);
-        }
-    }
-
-    @Override
-    public String toString() {
-        if(mParentSession != null && mIsStartedFromActiveSession) {
-            // Log.startSession was called from within another active session. Use the parent's
-            // Id instead of the child to reduce confusion.
-            return mParentSession.toString();
-        } else {
-            StringBuilder methodName = new StringBuilder();
-            methodName.append(mShortMethodName);
-            if(mOwnerInfo != null && !mOwnerInfo.isEmpty()) {
-                methodName.append("(InCall package: ");
-                methodName.append(mOwnerInfo);
-                methodName.append(")");
-            }
-            return methodName.toString() + "@" + getFullSessionId();
-        }
-    }
-}
diff --git a/src/com/android/server/telecom/StatusBarNotifier.java b/src/com/android/server/telecom/StatusBarNotifier.java
index d8ede59..af3493e 100644
--- a/src/com/android/server/telecom/StatusBarNotifier.java
+++ b/src/com/android/server/telecom/StatusBarNotifier.java
@@ -18,6 +18,7 @@
 
 import android.app.StatusBarManager;
 import android.content.Context;
+import android.telecom.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 
diff --git a/src/com/android/server/telecom/SystemStateProvider.java b/src/com/android/server/telecom/SystemStateProvider.java
index 0b636cf..e1938b1 100644
--- a/src/com/android/server/telecom/SystemStateProvider.java
+++ b/src/com/android/server/telecom/SystemStateProvider.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.Configuration;
+import android.telecom.Log;
 
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArraySet;
diff --git a/src/com/android/server/telecom/TelecomBroadcastIntentProcessor.java b/src/com/android/server/telecom/TelecomBroadcastIntentProcessor.java
index c5db6de..60bfe16 100644
--- a/src/com/android/server/telecom/TelecomBroadcastIntentProcessor.java
+++ b/src/com/android/server/telecom/TelecomBroadcastIntentProcessor.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.UserHandle;
+import android.telecom.Log;
 
 public final class TelecomBroadcastIntentProcessor {
     /** The action used to send SMS response for the missed call notification. */
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index c93a752..5d6662c 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -39,6 +39,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.telecom.DefaultDialerManager;
+import android.telecom.Log;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomAnalytics;
@@ -1194,7 +1195,7 @@
                 pw.decreaseIndent();
             }
 
-            Log.dumpCallEvents(pw);
+            Log.dumpEvents(pw);
         }
 
         /**
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index d665a82..5bbce5c 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -31,6 +31,7 @@
 import android.content.IntentFilter;
 import android.net.Uri;
 import android.os.UserHandle;
+import android.telecom.Log;
 
 import java.io.FileNotFoundException;
 import java.io.InputStream;
@@ -182,8 +183,7 @@
             PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
             InterruptionFilterProxy interruptionFilterProxy) {
         mContext = context.getApplicationContext();
-        Log.setContext(mContext);
-        Log.initMd5Sum();
+        LogUtils.initLogging(mContext);
 
         Log.startSession("TS.init");
         mPhoneAccountRegistrar = new PhoneAccountRegistrar(mContext);
diff --git a/src/com/android/server/telecom/TelecomWakeLock.java b/src/com/android/server/telecom/TelecomWakeLock.java
index 9fca19e..185e111 100644
--- a/src/com/android/server/telecom/TelecomWakeLock.java
+++ b/src/com/android/server/telecom/TelecomWakeLock.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.os.PowerManager;
+import android.telecom.Log;
 
 /**
  * Container for PowerManager / PowerManager.WakeLock access in telecom to facilitate unit testing.
diff --git a/src/com/android/server/telecom/ThreadUtil.java b/src/com/android/server/telecom/ThreadUtil.java
index 650e73f..571d529 100644
--- a/src/com/android/server/telecom/ThreadUtil.java
+++ b/src/com/android/server/telecom/ThreadUtil.java
@@ -17,6 +17,7 @@
 package com.android.server.telecom;
 
 import android.os.Looper;
+import android.telecom.Log;
 
 /**
  * Helper methods to deal with threading related tasks.
diff --git a/src/com/android/server/telecom/Timeouts.java b/src/com/android/server/telecom/Timeouts.java
index 7be59c3..f837947 100644
--- a/src/com/android/server/telecom/Timeouts.java
+++ b/src/com/android/server/telecom/Timeouts.java
@@ -121,15 +121,6 @@
     }
 
     /**
-     * Returns the amount of time after a Logging session has been started that Telecom is set to
-     * perform a sweep to check and make sure that the session is still not incomplete (stale).
-     */
-    public static long getStaleSessionCleanupTimeoutMillis(ContentResolver contentResolver) {
-        return get(contentResolver, "stale_session_cleanup_timeout_millis",
-                Log.DEFAULT_SESSION_TIMEOUT_MS);
-    }
-
-    /**
      * Returns the amount of time to wait for the call screening service to allow or disallow a
      * call.
      */
diff --git a/src/com/android/server/telecom/TtyManager.java b/src/com/android/server/telecom/TtyManager.java
index 25284e4..2d04234 100644
--- a/src/com/android/server/telecom/TtyManager.java
+++ b/src/com/android/server/telecom/TtyManager.java
@@ -23,6 +23,7 @@
 import android.media.AudioManager;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.telecom.Log;
 import android.telecom.TelecomManager;
 
 import com.android.internal.util.IndentingPrintWriter;
diff --git a/src/com/android/server/telecom/VideoProviderProxy.java b/src/com/android/server/telecom/VideoProviderProxy.java
index 3722b59..fe3bbea 100644
--- a/src/com/android/server/telecom/VideoProviderProxy.java
+++ b/src/com/android/server/telecom/VideoProviderProxy.java
@@ -22,6 +22,7 @@
 import android.os.RemoteException;
 import android.telecom.Connection;
 import android.telecom.InCallService;
+import android.telecom.Log;
 import android.telecom.VideoProfile;
 import android.view.Surface;
 
@@ -129,7 +130,7 @@
                 Log.startSession("VPP.rSMR");
                 synchronized (mLock) {
                     logFromVideoProvider("receiveSessionModifyRequest: " + videoProfile);
-                    Log.event(mCall, Log.Events.RECEIVE_VIDEO_REQUEST,
+                    Log.addEvent(mCall, LogUtils.Events.RECEIVE_VIDEO_REQUEST,
                             VideoProfile.videoStateToString(videoProfile.getVideoState()));
 
                     mCall.getAnalytics().addVideoEvent(
@@ -142,7 +143,7 @@
                         // a request to upgrade to video, automatically reject it without informing
                         // the InCallService.
 
-                        Log.event(mCall, Log.Events.SEND_VIDEO_RESPONSE, "video not supported");
+                        Log.addEvent(mCall, LogUtils.Events.SEND_VIDEO_RESPONSE, "video not supported");
                         VideoProfile responseProfile = new VideoProfile(
                                 VideoProfile.STATE_AUDIO_ONLY);
                         try {
@@ -182,7 +183,7 @@
                     " requestProfile=" + requestProfile + " responseProfile=" + responseProfile);
             String eventMessage = "Status Code : " + status + " Video State: " +
                     (responseProfile != null ? responseProfile.getVideoState() : "null");
-            Log.event(mCall, Log.Events.RECEIVE_VIDEO_RESPONSE, eventMessage);
+            Log.addEvent(mCall, LogUtils.Events.RECEIVE_VIDEO_RESPONSE, eventMessage);
             synchronized (mLock) {
                 if (status == Connection.VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS) {
                     mCall.getAnalytics().addVideoEvent(
@@ -371,7 +372,7 @@
     public void onSendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
         synchronized (mLock) {
             logFromInCall("sendSessionModifyRequest: from=" + fromProfile + " to=" + toProfile);
-            Log.event(mCall, Log.Events.SEND_VIDEO_REQUEST,
+            Log.addEvent(mCall, LogUtils.Events.SEND_VIDEO_REQUEST,
                     VideoProfile.videoStateToString(toProfile.getVideoState()));
             mCall.getAnalytics().addVideoEvent(
                     Analytics.SEND_LOCAL_SESSION_MODIFY_REQUEST,
@@ -393,7 +394,7 @@
     public void onSendSessionModifyResponse(VideoProfile responseProfile) {
         synchronized (mLock) {
             logFromInCall("sendSessionModifyResponse: " + responseProfile);
-            Log.event(mCall, Log.Events.SEND_VIDEO_RESPONSE,
+            Log.addEvent(mCall, LogUtils.Events.SEND_VIDEO_RESPONSE,
                     VideoProfile.videoStateToString(responseProfile.getVideoState()));
             mCall.getAnalytics().addVideoEvent(
                     Analytics.SEND_LOCAL_SESSION_MODIFY_RESPONSE,
diff --git a/src/com/android/server/telecom/WiredHeadsetManager.java b/src/com/android/server/telecom/WiredHeadsetManager.java
index 5bd49f5..a5e4404 100644
--- a/src/com/android/server/telecom/WiredHeadsetManager.java
+++ b/src/com/android/server/telecom/WiredHeadsetManager.java
@@ -20,6 +20,7 @@
 import android.media.AudioDeviceCallback;
 import android.media.AudioDeviceInfo;
 import android.media.AudioManager;
+import android.telecom.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
diff --git a/src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java b/src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java
index 51fc390..2f78d23 100644
--- a/src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java
+++ b/src/com/android/server/telecom/callfiltering/AsyncBlockCheckFilter.java
@@ -18,10 +18,11 @@
 
 import android.content.Context;
 import android.os.AsyncTask;
+import android.telecom.Log;
+import android.telecom.Logging.Session;
 
 import com.android.server.telecom.Call;
-import com.android.server.telecom.Log;
-import com.android.server.telecom.Session;
+import com.android.server.telecom.LogUtils;
 
 /**
  * An {@link AsyncTask} that checks if a call needs to be blocked.
@@ -61,7 +62,7 @@
     protected Boolean doInBackground(String... params) {
         try {
             Log.continueSession(mBackgroundTaskSubsession, "ABCF.dIB");
-            Log.event(mIncomingCall, Log.Events.BLOCK_CHECK_INITIATED);
+            Log.addEvent(mIncomingCall, LogUtils.Events.BLOCK_CHECK_INITIATED);
             return mBlockCheckerAdapter.isBlocked(mContext, params[0]);
         } finally {
             Log.endSession();
@@ -88,7 +89,7 @@
                         true // shouldShowNotification
                 );
             }
-            Log.event(mIncomingCall, Log.Events.BLOCK_CHECK_FINISHED, result);
+            Log.addEvent(mIncomingCall, LogUtils.Events.BLOCK_CHECK_FINISHED, result);
             mCallback.onCallFilteringComplete(mIncomingCall, result);
         } finally {
             Log.endSession();
diff --git a/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java b/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java
index db99e2f..44f5aad 100644
--- a/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java
+++ b/src/com/android/server/telecom/callfiltering/CallScreeningServiceFilter.java
@@ -27,13 +27,14 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.telecom.CallScreeningService;
+import android.telecom.Log;
 import android.text.TextUtils;
 
 import com.android.internal.telecom.ICallScreeningAdapter;
 import com.android.internal.telecom.ICallScreeningService;
 import com.android.server.telecom.Call;
 import com.android.server.telecom.CallsManager;
-import com.android.server.telecom.Log;
+import com.android.server.telecom.LogUtils;
 import com.android.server.telecom.ParcelableCallUtils;
 import com.android.server.telecom.PhoneAccountRegistrar;
 import com.android.server.telecom.TelecomServiceImpl;
@@ -52,7 +53,7 @@
             Log.startSession("CSCR.oSC");
             try {
                 synchronized (mTelecomLock) {
-                    Log.event(mCall, Log.Events.SCREENING_BOUND, componentName);
+                    Log.addEvent(mCall, LogUtils.Events.SCREENING_BOUND, componentName);
                     if (!mHasFinished) {
                         onServiceBound(ICallScreeningService.Stub.asInterface(service));
                     }
@@ -174,7 +175,7 @@
             Log.w(this, "Attempting to reuse CallScreeningServiceFilter. Ignoring.");
             return;
         }
-        Log.event(call, Log.Events.SCREENING_SENT);
+        Log.addEvent(call, LogUtils.Events.SCREENING_SENT);
         mCall = call;
         mCallback = callback;
         if (!bindService()) {
@@ -185,7 +186,7 @@
 
     private void finishCallScreening() {
         if (!mHasFinished) {
-            Log.event(mCall, Log.Events.SCREENING_COMPLETED, mResult);
+            Log.addEvent(mCall, LogUtils.Events.SCREENING_COMPLETED, mResult);
             mCallback.onCallFilteringComplete(mCall, mResult);
 
             if (mConnection != null) {
@@ -230,7 +231,7 @@
 
         ComponentName componentName =
                 new ComponentName(entry.serviceInfo.packageName, entry.serviceInfo.name);
-        Log.event(mCall, Log.Events.BIND_SCREENING, componentName);
+        Log.addEvent(mCall, LogUtils.Events.BIND_SCREENING, componentName);
         intent.setComponent(componentName);
         ServiceConnection connection = new CallScreeningServiceConnection();
         if (mContext.bindServiceAsUser(
diff --git a/src/com/android/server/telecom/callfiltering/DirectToVoicemailCallFilter.java b/src/com/android/server/telecom/callfiltering/DirectToVoicemailCallFilter.java
index 1aaae46..41e4351 100644
--- a/src/com/android/server/telecom/callfiltering/DirectToVoicemailCallFilter.java
+++ b/src/com/android/server/telecom/callfiltering/DirectToVoicemailCallFilter.java
@@ -17,11 +17,12 @@
 package com.android.server.telecom.callfiltering;
 
 import android.net.Uri;
+import android.telecom.Log;
 
 import com.android.internal.telephony.CallerInfo;
 import com.android.server.telecom.Call;
 import com.android.server.telecom.CallerInfoLookupHelper;
-import com.android.server.telecom.Log;
+import com.android.server.telecom.LogUtils;
 
 import java.util.Objects;
 
@@ -34,7 +35,7 @@
 
     @Override
     public void startFilterLookup(final Call call, CallFilterResultCallback callback) {
-        Log.event(call, Log.Events.DIRECT_TO_VM_INITIATED);
+        Log.addEvent(call, LogUtils.Events.DIRECT_TO_VM_INITIATED);
         final Uri callHandle = call.getHandle();
 
         mCallerInfoLookupHelper.startLookup(callHandle,
@@ -58,7 +59,7 @@
                                         true // shouldShowNotification
                                 );
                             }
-                            Log.event(call, Log.Events.DIRECT_TO_VM_FINISHED, result);
+                            Log.addEvent(call, LogUtils.Events.DIRECT_TO_VM_FINISHED, result);
                             callback.onCallFilteringComplete(call, result);
                         } else {
                             Log.w(this, "CallerInfo lookup returned with a different handle than " +
diff --git a/src/com/android/server/telecom/callfiltering/IncomingCallFilter.java b/src/com/android/server/telecom/callfiltering/IncomingCallFilter.java
index 6e0c684..1c947d1 100644
--- a/src/com/android/server/telecom/callfiltering/IncomingCallFilter.java
+++ b/src/com/android/server/telecom/callfiltering/IncomingCallFilter.java
@@ -19,11 +19,12 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
+import android.telecom.Log;
+import android.telecom.Logging.Runnable;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.telecom.Call;
-import com.android.server.telecom.Log;
-import com.android.server.telecom.Runnable;
+import com.android.server.telecom.LogUtils;
 import com.android.server.telecom.TelecomSystem;
 import com.android.server.telecom.Timeouts;
 
@@ -66,7 +67,7 @@
     }
 
     public void performFiltering() {
-        Log.event(mCall, Log.Events.FILTERING_INITIATED);
+        Log.addEvent(mCall, LogUtils.Events.FILTERING_INITIATED);
         for (CallFilter filter : mFilters) {
             filter.startFilterLookup(mCall, this);
         }
@@ -76,7 +77,7 @@
             public void loggedRun() {
                 if (mIsPending) {
                     Log.i(IncomingCallFilter.this, "Call filtering has timed out.");
-                    Log.event(mCall, Log.Events.FILTERING_TIMED_OUT);
+                    Log.addEvent(mCall, LogUtils.Events.FILTERING_TIMED_OUT);
                     mListener.onCallFilteringComplete(mCall, mResult);
                     mIsPending = false;
                 }
@@ -94,7 +95,7 @@
                     @Override
                     public void loggedRun() {
                         if (mIsPending) {
-                            Log.event(mCall, Log.Events.FILTERING_COMPLETED, mResult);
+                            Log.addEvent(mCall, LogUtils.Events.FILTERING_COMPLETED, mResult);
                             mListener.onCallFilteringComplete(mCall, mResult);
                             mIsPending = false;
                         }
diff --git a/src/com/android/server/telecom/components/ErrorDialogActivity.java b/src/com/android/server/telecom/components/ErrorDialogActivity.java
index 473767a..1bdcdf2 100644
--- a/src/com/android/server/telecom/components/ErrorDialogActivity.java
+++ b/src/com/android/server/telecom/components/ErrorDialogActivity.java
@@ -16,7 +16,6 @@
 
 package com.android.server.telecom.components;
 
-import com.android.server.telecom.Log;
 import com.android.server.telecom.R;
 
 import android.app.Activity;
@@ -24,6 +23,7 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.os.Bundle;
+import android.telecom.Log;
 
 // TODO: Needed for move to system service: import com.android.internal.R;
 
diff --git a/src/com/android/server/telecom/components/PrimaryCallReceiver.java b/src/com/android/server/telecom/components/PrimaryCallReceiver.java
index a05f04e..f19a243 100644
--- a/src/com/android/server/telecom/components/PrimaryCallReceiver.java
+++ b/src/com/android/server/telecom/components/PrimaryCallReceiver.java
@@ -1,11 +1,11 @@
 package com.android.server.telecom.components;
 
-import com.android.server.telecom.Log;
 import com.android.server.telecom.TelecomSystem;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.telecom.Log;
 
 /**
  * Single point of entry for all outgoing and incoming calls. {@link UserCallIntentProcessor} serves
diff --git a/src/com/android/server/telecom/components/TelecomService.java b/src/com/android/server/telecom/components/TelecomService.java
index c7fd9e0..d3cd073 100644
--- a/src/com/android/server/telecom/components/TelecomService.java
+++ b/src/com/android/server/telecom/components/TelecomService.java
@@ -26,6 +26,7 @@
 import android.os.IBinder;
 import android.os.PowerManager;
 import android.os.ServiceManager;
+import android.telecom.Log;
 
 import com.android.internal.telephony.CallerInfoAsyncQuery;
 import com.android.server.telecom.AsyncRingtonePlayer;
@@ -43,7 +44,6 @@
 import com.android.server.telecom.PhoneNumberUtilsAdapterImpl;
 import com.android.server.telecom.ProximitySensorManagerFactory;
 import com.android.server.telecom.InCallWakeLockController;
-import com.android.server.telecom.Log;
 import com.android.server.telecom.ProximitySensorManager;
 import com.android.server.telecom.TelecomSystem;
 import com.android.server.telecom.TelecomWakeLock;
diff --git a/src/com/android/server/telecom/components/UserCallActivity.java b/src/com/android/server/telecom/components/UserCallActivity.java
index 3188f45..1a3c77a 100644
--- a/src/com/android/server/telecom/components/UserCallActivity.java
+++ b/src/com/android/server/telecom/components/UserCallActivity.java
@@ -17,7 +17,6 @@
 package com.android.server.telecom.components;
 
 import com.android.server.telecom.CallIntentProcessor;
-import com.android.server.telecom.Log;
 import com.android.server.telecom.TelecomSystem;
 
 import android.app.Activity;
@@ -26,6 +25,7 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.telecom.Log;
 import android.telecom.TelecomManager;
 
 // TODO: Needed for move to system service: import com.android.internal.R;
diff --git a/src/com/android/server/telecom/components/UserCallIntentProcessor.java b/src/com/android/server/telecom/components/UserCallIntentProcessor.java
index a513bcf..a95768e 100644
--- a/src/com/android/server/telecom/components/UserCallIntentProcessor.java
+++ b/src/com/android/server/telecom/components/UserCallIntentProcessor.java
@@ -17,7 +17,6 @@
 package com.android.server.telecom.components;
 
 import com.android.server.telecom.CallIntentProcessor;
-import com.android.server.telecom.Log;
 import com.android.server.telecom.R;
 import com.android.server.telecom.TelephonyUtil;
 import com.android.server.telecom.UserUtil;
@@ -32,6 +31,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.telecom.DefaultDialerManager;
+import android.telecom.Log;
 import android.telecom.PhoneAccount;
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
diff --git a/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java b/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
index e73b57c..2bc1e2b 100644
--- a/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
+++ b/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
@@ -22,17 +22,16 @@
 import android.content.ComponentName;
 import android.content.ContentProvider;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.telecom.Logging.Runnable;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
 
 import com.android.server.telecom.CallerInfoLookupHelper;
 import com.android.server.telecom.CallsManagerListenerBase;
 import com.android.server.telecom.Constants;
-import com.android.server.telecom.Log;
 import com.android.server.telecom.MissedCallNotifier;
 import com.android.server.telecom.PhoneAccountRegistrar;
 import com.android.server.telecom.R;
-import com.android.server.telecom.Runnable;
 import com.android.server.telecom.TelecomBroadcastIntentProcessor;
 import com.android.server.telecom.TelecomSystem;
 import com.android.server.telecom.components.TelecomBroadcastReceiver;
@@ -56,6 +55,7 @@
 import android.os.UserHandle;
 import android.provider.CallLog.Calls;
 import android.telecom.DefaultDialerManager;
+import android.telecom.Log;
 import android.telecom.PhoneAccount;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.TelephonyManager;
@@ -70,7 +70,6 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Objects;
-import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicInteger;
diff --git a/tests/src/com/android/server/telecom/tests/AnalyticsTests.java b/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
index 81d4aa5..b22ae82 100644
--- a/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
+++ b/tests/src/com/android/server/telecom/tests/AnalyticsTests.java
@@ -20,6 +20,7 @@
 import android.telecom.Connection;
 import android.telecom.DisconnectCause;
 import android.telecom.InCallService;
+import android.telecom.Log;
 import android.telecom.ParcelableCallAnalytics;
 import android.telecom.TelecomAnalytics;
 import android.telecom.TelecomManager;
@@ -31,7 +32,7 @@
 
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.telecom.Analytics;
-import com.android.server.telecom.Log;
+import com.android.server.telecom.LogUtils;
 import com.android.server.telecom.TelecomLogClass;
 
 import java.io.PrintWriter;
@@ -244,13 +245,13 @@
     @SmallTest
     public void testAnalyticsLogSessionTiming() throws Exception {
         long minTime = 50;
-        Log.startSession(Log.Sessions.CSW_ADD_CONFERENCE_CALL);
+        Log.startSession(LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL);
         Thread.sleep(minTime);
         Log.endSession();
         TelecomManager tm = (TelecomManager) mSpyContext.getSystemService(Context.TELECOM_SERVICE);
         List<TelecomAnalytics.SessionTiming> sessions = tm.dumpAnalytics().getSessionTimings();
         sessions.stream()
-                .filter(s -> Log.Sessions.CSW_ADD_CONFERENCE_CALL.equals(
+                .filter(s -> LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL.equals(
                         Analytics.sSessionIdToLogSession.get(s.getKey())))
                 .forEach(s -> assertTrue(s.getTime() >= minTime));
     }
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index 1ab1070..488816c 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -41,6 +41,7 @@
 import android.telecom.Connection;
 import android.telecom.ConnectionRequest;
 import android.telecom.DisconnectCause;
+import android.telecom.Log;
 import android.telecom.ParcelableCall;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
@@ -51,7 +52,6 @@
 
 import com.android.internal.telecom.IInCallAdapter;
 import com.android.internal.telephony.CallerInfo;
-import com.android.server.telecom.Log;
 
 import com.google.common.base.Predicate;
 
diff --git a/tests/src/com/android/server/telecom/tests/CallerInfoAsyncQueryFactoryFixture.java b/tests/src/com/android/server/telecom/tests/CallerInfoAsyncQueryFactoryFixture.java
index 290fa7a..5f9555c 100644
--- a/tests/src/com/android/server/telecom/tests/CallerInfoAsyncQueryFactoryFixture.java
+++ b/tests/src/com/android/server/telecom/tests/CallerInfoAsyncQueryFactoryFixture.java
@@ -19,9 +19,9 @@
 import com.android.internal.telephony.CallerInfo;
 import com.android.internal.telephony.CallerInfoAsyncQuery;
 import com.android.server.telecom.CallerInfoAsyncQueryFactory;
-import com.android.server.telecom.Log;
 
 import android.content.Context;
+import android.telecom.Log;
 
 import org.mockito.Mockito;
 
diff --git a/tests/src/com/android/server/telecom/tests/CallerInfoLookupHelperTest.java b/tests/src/com/android/server/telecom/tests/CallerInfoLookupHelperTest.java
index f261d3e..2ae717d 100644
--- a/tests/src/com/android/server/telecom/tests/CallerInfoLookupHelperTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallerInfoLookupHelperTest.java
@@ -22,6 +22,7 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.telecom.Logging.Session;
 
 import com.android.internal.telephony.CallerInfo;
 import com.android.internal.telephony.CallerInfoAsyncQuery;
@@ -29,7 +30,6 @@
 import com.android.server.telecom.CallerInfoAsyncQueryFactory;
 import com.android.server.telecom.CallerInfoLookupHelper;
 import com.android.server.telecom.ContactsAsyncHelper;
-import com.android.server.telecom.Session;
 import com.android.server.telecom.TelecomSystem;
 
 import org.mockito.ArgumentCaptor;
diff --git a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
index 5ed941e..65352f9 100644
--- a/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ComponentContextFixture.java
@@ -21,7 +21,6 @@
 
 import com.android.internal.telecom.IConnectionService;
 import com.android.internal.telecom.IInCallService;
-import com.android.server.telecom.Log;
 
 import org.mockito.MockitoAnnotations;
 import org.mockito.invocation.InvocationOnMock;
@@ -53,6 +52,7 @@
 import android.os.UserManager;
 import android.telecom.CallAudioState;
 import android.telecom.ConnectionService;
+import android.telecom.Log;
 import android.telecom.InCallService;
 import android.telecom.PhoneAccount;
 import android.telecom.TelecomManager;
diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
index 255f3ea..158c3a8 100644
--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
@@ -20,7 +20,6 @@
 import com.android.internal.telecom.IConnectionServiceAdapter;
 import com.android.internal.telecom.IVideoProvider;
 import com.android.internal.telecom.RemoteServiceCallback;
-import com.android.server.telecom.Log;
 
 import junit.framework.TestCase;
 
@@ -38,6 +37,7 @@
 import android.telecom.ConnectionRequest;
 import android.telecom.ConnectionService;
 import android.telecom.DisconnectCause;
+import android.telecom.Log;
 import android.telecom.ParcelableConference;
 import android.telecom.ParcelableConnection;
 import android.telecom.PhoneAccountHandle;
diff --git a/tests/src/com/android/server/telecom/tests/LogTest.java b/tests/src/com/android/server/telecom/tests/LogTest.java
deleted file mode 100644
index 0665338..0000000
--- a/tests/src/com/android/server/telecom/tests/LogTest.java
+++ /dev/null
@@ -1,579 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.telecom.tests;
-
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Message;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.internal.os.SomeArgs;
-import com.android.server.telecom.Analytics;
-import com.android.server.telecom.Call;
-import com.android.server.telecom.Session;
-import com.android.server.telecom.SystemLoggingContainer;
-import com.android.server.telecom.Log;
-
-import org.junit.Assert;
-import org.mockito.ArgumentCaptor;
-import org.mockito.MockitoAnnotations;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-/**
- * Unit tests for Telecom's Logging system.
- */
-public class LogTest extends TelecomTestCase{
-
-    /**
-     * This helper class captures the logs that are sent to Log and stores them in an array to be
-     * verified by LogTest.
-     */
-    private class TestLoggingContainer extends SystemLoggingContainer {
-        public ArrayList<String> receivedStrings;
-
-        public TestLoggingContainer() {
-            receivedStrings = new ArrayList<>(100);
-        }
-
-        @Override
-        public synchronized void v(String msgTag, String msg) {
-            if (msgTag.equals(LogTest.TESTING_TAG)) {
-                synchronized (this) {
-                    receivedStrings.add(processMessage(msg));
-                }
-            }
-        }
-
-        @Override
-        public synchronized void i(String msgTag, String msg) {
-            if (msgTag.equals(LogTest.TESTING_TAG)) {
-                synchronized (this) {
-                    receivedStrings.add(processMessage(msg));
-                }
-            }
-        }
-
-        public boolean didReceiveMessage(int timeoutMs, String msg) {
-            String matchedString = null;
-            // Wait for timeout to expire before checking received messages
-            if (timeoutMs > 0) {
-                try {
-                    Thread.sleep(timeoutMs);
-                } catch (InterruptedException e) {
-                    Log.w(LogTest.TESTING_TAG, "TestLoggingContainer: Thread Interrupted!");
-                }
-            }
-            synchronized (this) {
-                for (String receivedString : receivedStrings) {
-                    if (receivedString.contains(msg)) {
-                        matchedString = receivedString;
-                        break;
-                    }
-                }
-                if (matchedString != null) {
-                    receivedStrings.remove(matchedString);
-                    return true;
-                }
-            }
-            android.util.Log.i(TESTING_TAG, "Did not receive message: " + msg);
-            return false;
-        }
-
-        public boolean isMessagesEmpty() {
-            boolean isEmpty = receivedStrings.isEmpty();
-            if (!isEmpty) {
-                printMessagesThatAreLeft();
-            }
-            return isEmpty;
-        }
-
-        public synchronized void printMessagesThatAreLeft() {
-            android.util.Log.i(TESTING_TAG, "Remaining Messages in Log Queue:");
-            for (String receivedString : receivedStrings) {
-                android.util.Log.i(TESTING_TAG, "\t- " + receivedString);
-            }
-        }
-
-        // Remove Unnecessary parts of message string before processing
-        private String processMessage(String msg) {
-            if(msg.contains(Session.CREATE_SUBSESSION)) {
-                return clipMsg(Session.CREATE_SUBSESSION, msg);
-            }
-            if(msg.contains(Session.CONTINUE_SUBSESSION)) {
-                return clipMsg(Session.CONTINUE_SUBSESSION, msg);
-            }
-            if (msg.contains(Session.END_SUBSESSION)) {
-                return clipMsg(Session.END_SUBSESSION, msg);
-            }
-            if (msg.contains(Session.END_SESSION)) {
-                return clipMsg(Session.END_SESSION, msg);
-            }
-            return msg;
-        }
-
-        private String clipMsg(String id, String msg) {
-                int clipStartIndex = msg.indexOf(id) + id.length();
-                int clipEndIndex = msg.lastIndexOf(":");
-                return msg.substring(0, clipStartIndex) + msg.substring(clipEndIndex, msg.length());
-        }
-    }
-
-    public static final int TEST_THREAD_COUNT = 150;
-    public static final int TEST_SLEEP_TIME_MS = 50;
-    // Should be larger than TEST_SLEEP_TIME_MS!
-    public static final int TEST_VERIFY_TIMEOUT_MS = 100;
-    public static final String TEST_ENTER_METHOD1 = "TEM1";
-    public static final String TEST_ENTER_METHOD2 = "TEM2";
-    public static final String TEST_ENTER_METHOD3 = "TEM3";
-    public static final String TEST_ENTER_METHOD4 = "TEM4";
-    public static final String TEST_CLASS_NAME = "LogTest";
-
-    private static final int EVENT_START_TEST_SLEEPY_METHOD = 0;
-    private static final int EVENT_START_TEST_SLEEPY_MULTIPLE_METHOD = 1;
-    private static final int EVENT_LAST_MESSAGE = 2;
-
-    private static final long RANDOM_NUMBER_SEED = 6191991;
-
-    Random rng = new Random(RANDOM_NUMBER_SEED);
-
-    private Handler mSleepyHandler = new Handler(
-            new HandlerThread("sleepyThread"){{start();}}.getLooper()) {
-        @Override
-        public void handleMessage(Message msg) {
-            SomeArgs args = (SomeArgs) msg.obj;
-            Session subsession = (Session) args.arg1;
-            Log.continueSession(subsession, "lTSH.hM");
-            switch (msg.what) {
-                case EVENT_START_TEST_SLEEPY_METHOD:
-                    sleepyMethod(TEST_SLEEP_TIME_MS);
-                    break;
-            }
-            Log.endSession();
-        }
-    };
-
-    private boolean isHandlerCompleteWithEvents;
-    private Handler mSleepyMultipleHandler = new Handler(
-            new HandlerThread("sleepyMultipleThread"){{start();}}.getLooper()){
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case EVENT_START_TEST_SLEEPY_MULTIPLE_METHOD:
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    Session subsession = (Session) args.arg1;
-                    Log.continueSession(subsession, "lTSCH.hM");
-                    sleepyMultipleMethod();
-                    Log.endSession();
-                    break;
-                case EVENT_LAST_MESSAGE:
-                    isHandlerCompleteWithEvents = true;
-                    break;
-            }
-        }
-    };
-
-    private AtomicInteger mCompleteCount;
-    class LogTestRunnable implements java.lang.Runnable {
-        private String mshortMethodName;
-        public LogTestRunnable(String shortMethodName) {
-            mshortMethodName = shortMethodName;
-        }
-
-        public void run() {
-            Log.startSession(mshortMethodName);
-            sleepyCallerMethod(TEST_SLEEP_TIME_MS);
-            Log.endSession();
-            mCompleteCount.incrementAndGet();
-        }
-    }
-
-    TestLoggingContainer mTestSystemLogger;
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        MockitoAnnotations.initMocks(this);
-        mTestSystemLogger = new TestLoggingContainer();
-        Log.setLoggingContainer(mTestSystemLogger);
-        Log.setIsExtendedLoggingEnabled(true);
-        Log.restartSessionCounter();
-        Log.sCleanStaleSessions = null;
-        Log.sSessionMapper.clear();
-        Log.setContext(mComponentContextFixture.getTestDouble().getApplicationContext());
-        Log.sSessionCleanupTimeoutMs = new Log.ISessionCleanupTimeoutMs() {
-            @Override
-            // Set to the default value of Timeouts.getStaleSessionCleanupTimeoutMillis without
-            // needing to query.
-            public long get() {
-                return Log.DEFAULT_SESSION_TIMEOUT_MS;
-            }
-        };
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        mTestSystemLogger = null;
-        Log.setLoggingContainer(new SystemLoggingContainer());
-        super.tearDown();
-    }
-
-    @MediumTest
-    public void testSingleThreadSession() throws Exception {
-        String sessionName = "LT.sTS";
-        Log.startSession(sessionName);
-        sleepyMethod(TEST_SLEEP_TIME_MS);
-        Log.endSession();
-
-        verifyEventResult(Session.START_SESSION, sessionName, "", 0, TEST_VERIFY_TIMEOUT_MS);
-        verifyMethodCall("", sessionName, 0, "", TEST_ENTER_METHOD1, TEST_VERIFY_TIMEOUT_MS);
-        verifyEventResult(Session.END_SUBSESSION, sessionName, "", 0, TEST_VERIFY_TIMEOUT_MS);
-        verifyEndEventResult(sessionName, "", 0, TEST_VERIFY_TIMEOUT_MS);
-
-        assertEquals(Log.sSessionMapper.size(), 0);
-        assertEquals(true, mTestSystemLogger.isMessagesEmpty());
-    }
-
-    @MediumTest
-    public void testSingleHandlerThreadSession() throws Exception {
-        String sessionName = "LT.tSHTS";
-        Log.startSession(sessionName);
-        Session subsession = Log.createSubsession();
-        SomeArgs args = SomeArgs.obtain();
-        args.arg1 = subsession;
-        mSleepyHandler.obtainMessage(EVENT_START_TEST_SLEEPY_METHOD, args).sendToTarget();
-        Log.endSession();
-
-        verifyEventResult(Session.START_SESSION, sessionName, "", 0, TEST_VERIFY_TIMEOUT_MS);
-        verifyEventResult(Session.CREATE_SUBSESSION, sessionName, "", 0, TEST_VERIFY_TIMEOUT_MS);
-        verifyContinueEventResult(sessionName, "lTSH.hM", "_0", 0, TEST_VERIFY_TIMEOUT_MS);
-        verifyEventResult(Session.END_SUBSESSION, sessionName, "", 0, TEST_VERIFY_TIMEOUT_MS);
-        verifyMethodCall(sessionName, "lTSH.hM", 0, "_0", TEST_ENTER_METHOD1,
-                TEST_VERIFY_TIMEOUT_MS);
-        verifyEventResult(Session.END_SUBSESSION, sessionName + "->lTSH.hM", "_0", 0,
-                TEST_VERIFY_TIMEOUT_MS);
-        verifyEndEventResult(sessionName, "", 0, TEST_VERIFY_TIMEOUT_MS);
-
-        assertEquals(Log.sSessionMapper.size(), 0);
-        assertEquals(true, mTestSystemLogger.isMessagesEmpty());
-    }
-
-    @MediumTest
-    public void testSpawnMultipleThreadSessions() throws Exception {
-        final String sessionName = "LT.lTR";
-        mCompleteCount = new AtomicInteger(0);
-        for (int i = 0; i < TEST_THREAD_COUNT; i++) {
-            Thread.sleep(10);
-            new Thread(new LogTestRunnable(sessionName)).start();
-        }
-
-        // Poll until all of the threads have completed
-        while (mCompleteCount.get() < TEST_THREAD_COUNT) {
-            Thread.sleep(1000);
-        }
-
-        // Loop through verification separately to spawn threads fast so there is possible overlap
-        // (verifyEventResult(...) delays)
-        for (int i = 0; i < TEST_THREAD_COUNT; i++) {
-            verifyEventResult(Session.START_SESSION, sessionName, "", i, 0);
-            verifyMethodCall("", sessionName, i, "", TEST_ENTER_METHOD2, 0);
-            verifyMethodCall("", sessionName, i, "", TEST_ENTER_METHOD1, 0);
-            verifyEventResult(Session.END_SUBSESSION, sessionName, "", i, 0);
-            verifyEndEventResult(sessionName, "", i, 0);
-        }
-
-        assertEquals(Log.sSessionMapper.size(), 0);
-        assertEquals(true, mTestSystemLogger.isMessagesEmpty());
-    }
-
-    @MediumTest
-    public void testSpawnMultipleThreadMultipleHandlerSession() throws Exception {
-        String sessionName = "LT.tSMTMHS";
-        Log.startSession(sessionName);
-        Session subsession = Log.createSubsession();
-        SomeArgs args = SomeArgs.obtain();
-        args.arg1 = subsession;
-        mSleepyMultipleHandler.obtainMessage(EVENT_START_TEST_SLEEPY_MULTIPLE_METHOD,
-                args).sendToTarget();
-        Log.endSession();
-
-        verifyEventResult(Session.START_SESSION, sessionName, "", 0, TEST_VERIFY_TIMEOUT_MS);
-        verifyEventResult(Session.END_SUBSESSION, sessionName, "", 0, TEST_VERIFY_TIMEOUT_MS);
-        verifyEventResult(Session.CREATE_SUBSESSION, sessionName, "", 0, TEST_VERIFY_TIMEOUT_MS);
-        verifyContinueEventResult(sessionName, "lTSCH.hM", "_0", 0, TEST_VERIFY_TIMEOUT_MS);
-        verifyMethodCall(sessionName, "lTSCH.hM", 0, "_0", TEST_ENTER_METHOD3,
-                TEST_VERIFY_TIMEOUT_MS);
-        verifyEventResult(Session.END_SUBSESSION, sessionName + "->lTSCH.hM", "_0", 0,
-                TEST_VERIFY_TIMEOUT_MS);
-        verifyEventResult(Session.CREATE_SUBSESSION, sessionName + "->lTSCH.hM", "_0", 0,
-                TEST_VERIFY_TIMEOUT_MS);
-        verifyContinueEventResult(sessionName + "->" + "lTSCH.hM", "lTSH.hM", "_0_0", 0,
-                TEST_VERIFY_TIMEOUT_MS);
-        verifyMethodCall(sessionName + "->lTSCH.hM", "lTSH.hM", 0, "_0_0", TEST_ENTER_METHOD1,
-                TEST_VERIFY_TIMEOUT_MS);
-        verifyEventResult(Session.END_SUBSESSION, sessionName + "->lTSCH.hM->lTSH.hM", "_0_0", 0,
-                TEST_VERIFY_TIMEOUT_MS);
-        verifyEndEventResult(sessionName, "", 0, TEST_VERIFY_TIMEOUT_MS);
-
-        assertEquals(Log.sSessionMapper.size(), 0);
-        assertEquals(true, mTestSystemLogger.isMessagesEmpty());
-    }
-
-    @MediumTest
-    public void testSpawnMultipleThreadMultipleHandlerSessions() throws Exception {
-        String sessionName = "LT.tSMTMHSs";
-        isHandlerCompleteWithEvents = false;
-        for (int i = 0; i < TEST_THREAD_COUNT; i++) {
-            Log.startSession(sessionName);
-            Session subsession = Log.createSubsession();
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = subsession;
-            mSleepyMultipleHandler.obtainMessage(EVENT_START_TEST_SLEEPY_MULTIPLE_METHOD,
-                    args).sendToTarget();
-            Log.endSession();
-        }
-        // Send a message that denotes the last message that is sent. We poll until this message
-        // is processed in order to verify the results without waiting an arbitrary amount of time
-        // (that can change per device).
-        mSleepyMultipleHandler.obtainMessage(EVENT_LAST_MESSAGE).sendToTarget();
-
-        while (!isHandlerCompleteWithEvents) {
-            Thread.sleep(1000);
-        }
-
-        for (int i = 0; i < TEST_THREAD_COUNT; i++) {
-            verifyEventResult(Session.START_SESSION, sessionName, "", i, 0);
-            verifyEventResult(Session.END_SUBSESSION, sessionName, "", i, 0);
-            verifyEventResult(Session.CREATE_SUBSESSION, sessionName, "", i, 0);
-            verifyContinueEventResult(sessionName, "lTSCH.hM", "_0", i, 0);
-            verifyMethodCall(sessionName, "lTSCH.hM", i, "_0", TEST_ENTER_METHOD3, 0);
-            verifyEventResult(Session.END_SUBSESSION, sessionName + "->lTSCH.hM", "_0", i, 0);
-            verifyEventResult(Session.CREATE_SUBSESSION, sessionName + "->lTSCH.hM", "_0", i, 0);
-            verifyContinueEventResult(sessionName + "->" + "lTSCH.hM", "lTSH.hM", "_0_0", i, 0);
-            verifyMethodCall(sessionName + "->lTSCH.hM", "lTSH.hM", i, "_0_0", TEST_ENTER_METHOD1,
-                    0);
-            verifyEventResult(Session.END_SUBSESSION, sessionName + "->lTSCH.hM->lTSH.hM", "_0_0",
-                    i, 0);
-            verifyEndEventResult(sessionName, "", i, 0);
-        }
-
-        assertEquals(Log.sSessionMapper.size(), 0);
-        assertEquals(true, mTestSystemLogger.isMessagesEmpty());
-    }
-
-    @MediumTest
-    public void testCancelSubsession() throws Exception {
-        String sessionName = "LT.tCS";
-        Log.startSession(sessionName);
-        Session subsession = Log.createSubsession();
-        Log.cancelSubsession(subsession);
-        Log.endSession();
-
-        verifyEventResult(Session.START_SESSION, sessionName, "", 0, 0);
-        verifyEventResult(Session.CREATE_SUBSESSION, sessionName, "", 0, 0);
-        verifyEventResult(Session.END_SUBSESSION, sessionName, "", 0, 0);
-        verifyEndEventResult(sessionName, "", 0, 0);
-
-        assertEquals(Log.sSessionMapper.size(), 0);
-        assertEquals(true, mTestSystemLogger.isMessagesEmpty());
-    }
-
-    @MediumTest
-    public void testInternalExternalCallToMethod() throws Exception {
-        String sessionName = "LT.tIECTM";
-        Log.startSession(sessionName);
-        internalExternalMethod();
-        Log.endSession();
-
-        verifyEventResult(Session.START_SESSION, sessionName, "", 0, 0);
-        verifyEventResult(Session.CREATE_SUBSESSION, sessionName, "", 0, 0);
-        verifyContinueEventResult(sessionName, "", "", 0, 0);
-        verifyEventResult(Session.END_SUBSESSION, sessionName, "", 0, 0);
-        verifyMethodCall("", sessionName, 0, "", TEST_ENTER_METHOD4, 0);
-        verifyEventResult(Session.END_SUBSESSION, sessionName, "", 0, 0);
-        verifyEndEventResult(sessionName, "", 0, 0);
-
-        assertEquals(Log.sSessionMapper.size(), 0);
-        assertEquals(true, mTestSystemLogger.isMessagesEmpty());
-    }
-
-    @MediumTest
-    public void testGarbageCollectionWithTimeout() throws Exception {
-        String sessionName = "LT.tGCWT";
-
-        // Don't end session (Oops!)
-        Log.startSession(sessionName);
-        internalDanglingMethod();
-        Log.sSessionCleanupHandler.postDelayed(new java.lang.Runnable() {
-            @Override
-            public void run() {
-                android.util.Log.i(TESTING_TAG, "Running Test SessionCleanupHandler method.");
-                Log.cleanupStaleSessions(1000);
-            }
-        }, 1000);
-
-        verifyEventResult(Session.START_SESSION, sessionName, "", 0, 0);
-        verifyEventResult(Session.CREATE_SUBSESSION, sessionName, "", 0, 0);
-        verifyContinueEventResult(sessionName, "", "", 0, 0);
-        verifyMethodCall("", sessionName, 0, "", TEST_ENTER_METHOD4, 0);
-
-        // Verify the session is still active in mSessionMapper
-        assertEquals(Log.sSessionMapper.size(), 1);
-        assertEquals(true, mTestSystemLogger.isMessagesEmpty());
-
-        // Keep a weak reference to the object to check if it eventually gets garbage collected.
-        int threadId = Log.getCallingThreadId();
-        WeakReference<Session> sessionRef = new WeakReference<>(
-                Log.sSessionMapper.get(threadId));
-
-        Thread.sleep(1100);
-        assertEquals(0, Log.sSessionMapper.size());
-        // "Suggest" that the GC collects the now isolated Session and subsession and wait for it
-        // to occur. "System.gc()" was previously used, but it does not always perform GC, so the
-        // internal method is now called.
-        Runtime.getRuntime().gc();
-        Thread.sleep(1000);
-        assertEquals(null, sessionRef.get());
-    }
-
-    @SmallTest
-    public void testEventRecordTiming() throws Exception {
-        Call call = mock(Call.class);
-        Analytics.CallInfo mockCallInfo = mock(Analytics.CallInfo.class);
-        when(call.getAnalytics()).thenReturn(mockCallInfo);
-        int minWaitTime = 40;
-        Log.event(call, Log.Events.REQUEST_ACCEPT);
-        Thread.sleep(minWaitTime);
-        Log.event(call, Log.Events.SET_ACTIVE);
-
-        ArgumentCaptor<Log.CallEventRecord> captor =
-                ArgumentCaptor.forClass(Log.CallEventRecord.class);
-        verify(mockCallInfo).setCallEvents(captor.capture());
-        List<Log.CallEventRecord.EventTiming> eventTimings =
-                captor.getValue().extractEventTimings();
-        eventTimings.stream()
-                .filter(timing -> timing.name.equals("accept"))
-                .forEach(timing -> assertTrue(timing.time >= minWaitTime));
-    }
-
-    private void verifyMethodCall(String parentSessionName, String methodName, int sessionId,
-            String subsession, String shortMethodName, int timeoutMs) {
-        if (!parentSessionName.isEmpty()){
-            parentSessionName += "->";
-        }
-        boolean isMessageReceived = mTestSystemLogger.didReceiveMessage(timeoutMs,
-                buildExpectedResult(parentSessionName + methodName, sessionId, subsession,
-                        shortMethodName));
-
-        assertEquals(true, isMessageReceived);
-    }
-
-    private String buildExpectedSession(String shortMethodName, int sessionId) {
-        return shortMethodName + "@" + Log.getBase64Encoding(sessionId);
-    }
-
-    private String buildExpectedResult(String shortMethodName, int sessionId,
-            String subsessionId, String logText) {
-        return TEST_CLASS_NAME + ": " +  logText + ": " +
-                buildExpectedSession(shortMethodName, sessionId) + subsessionId;
-    }
-
-    private void verifyContinueEventResult(String shortOldMethodName, String shortNewMethodName,
-                String subsession, int sessionId, int timeoutMs) {
-        String expectedSession = buildExpectedSession(shortNewMethodName, sessionId);
-        if(!shortNewMethodName.isEmpty()) {
-            shortOldMethodName += "->";
-        }
-        boolean isMessageReceived = mTestSystemLogger.didReceiveMessage(timeoutMs,
-                Session.CONTINUE_SUBSESSION + ": " + shortOldMethodName + expectedSession +
-                        subsession);
-        assertEquals(true, isMessageReceived);
-    }
-
-    private void verifyEventResult(String event, String shortMethodName,  String subsession,
-            int sessionId, int timeoutMs) {
-        String expectedSession = buildExpectedSession(shortMethodName, sessionId);
-        boolean isMessageReceived = mTestSystemLogger.didReceiveMessage(timeoutMs,event + ": "  +
-                expectedSession + subsession);
-        assertEquals(true, isMessageReceived);
-    }
-
-    private void verifyEndEventResult(String shortMethodName, String subsession, int sessionId,
-            int timeoutMs) {
-        String expectedSession = buildExpectedSession(shortMethodName, sessionId);
-        boolean isMessageReceived = mTestSystemLogger.didReceiveMessage(timeoutMs,
-                Session.END_SESSION + ": " + expectedSession + subsession);
-        assertEquals(true, isMessageReceived);
-    }
-
-    private void internalExternalMethod() {
-        Log.startSession("LT.iEM");
-        Log.i(TEST_CLASS_NAME, TEST_ENTER_METHOD4);
-        Log.endSession();
-    }
-
-    private void internalDanglingMethod() {
-        Log.startSession("LT.iEM");
-        Log.i(TEST_CLASS_NAME, TEST_ENTER_METHOD4);
-    }
-
-    private void sleepyCallerMethod(int timeToSleepMs) {
-        Log.i(TEST_CLASS_NAME, TEST_ENTER_METHOD2);
-        try {
-            Thread.sleep(timeToSleepMs);
-            sleepyMethod(rng.nextInt(TEST_SLEEP_TIME_MS));
-        } catch (InterruptedException e) {
-            // This should not happen
-            Assert.fail("Thread sleep interrupted: " + e.getMessage());
-        }
-
-    }
-
-    private void sleepyMultipleMethod() {
-        Log.i(TEST_CLASS_NAME, TEST_ENTER_METHOD3);
-        Session subsession = Log.createSubsession();
-        SomeArgs args = SomeArgs.obtain();
-        args.arg1 = subsession;
-        mSleepyHandler.obtainMessage(EVENT_START_TEST_SLEEPY_METHOD, args).sendToTarget();
-        try {
-            Thread.sleep(TEST_SLEEP_TIME_MS);
-        } catch (InterruptedException e) {
-            // This should not happen
-            Assert.fail("Thread sleep interrupted: " + e.getMessage());
-        }
-    }
-
-    private void sleepyMethod(int timeToSleepMs) {
-        Log.i(TEST_CLASS_NAME, TEST_ENTER_METHOD1);
-        try {
-            Thread.sleep(timeToSleepMs);
-        } catch (InterruptedException e) {
-            // This should not happen
-            Assert.fail("Thread sleep interrupted: " + e.getMessage());
-        }
-    }
-}
\ No newline at end of file
diff --git a/tests/src/com/android/server/telecom/tests/MockitoHelper.java b/tests/src/com/android/server/telecom/tests/MockitoHelper.java
index 3425b0e..a28dfb0 100644
--- a/tests/src/com/android/server/telecom/tests/MockitoHelper.java
+++ b/tests/src/com/android/server/telecom/tests/MockitoHelper.java
@@ -16,9 +16,8 @@
 
 package com.android.server.telecom.tests;
 
-import com.android.server.telecom.Log;
-
 import android.content.Context;
+import android.telecom.Log;
 
 /**
  * Helper for Mockito-based test cases.
diff --git a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
index 12d24c4..7b5b836 100644
--- a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
+++ b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
@@ -26,6 +26,7 @@
 import android.os.Parcel;
 import android.os.Process;
 import android.os.UserHandle;
+import android.telecom.Log;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
@@ -34,7 +35,6 @@
 
 import com.android.internal.telecom.IConnectionService;
 import com.android.internal.util.FastXmlSerializer;
-import com.android.server.telecom.Log;
 import com.android.server.telecom.PhoneAccountRegistrar;
 import com.android.server.telecom.PhoneAccountRegistrar.DefaultPhoneAccountHandle;
 
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index 2652678..8edbe03 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -79,7 +79,6 @@
 import com.android.server.telecom.PhoneNumberUtilsAdapterImpl;
 import com.android.server.telecom.ProximitySensorManager;
 import com.android.server.telecom.ProximitySensorManagerFactory;
-import com.android.server.telecom.Runnable;
 import com.android.server.telecom.TelecomSystem;
 import com.android.server.telecom.Timeouts;
 import com.android.server.telecom.callfiltering.AsyncBlockCheckFilter;
diff --git a/tests/src/com/android/server/telecom/tests/TelecomTestCase.java b/tests/src/com/android/server/telecom/tests/TelecomTestCase.java
index ed10e4b..b909a54 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomTestCase.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomTestCase.java
@@ -16,11 +16,10 @@
 
 package com.android.server.telecom.tests;
 
-import com.android.server.telecom.Log;
-
 import org.mockito.MockitoAnnotations;
 
 import android.os.Handler;
+import android.telecom.Log;
 import android.test.AndroidTestCase;
 
 import java.util.concurrent.CountDownLatch;
@@ -37,8 +36,7 @@
         Log.setTag(TESTING_TAG);
         mMockitoHelper.setUp(getContext(), getClass());
         mComponentContextFixture = new ComponentContextFixture();
-        Log.setContext(mComponentContextFixture.getTestDouble().getApplicationContext());
-        Log.sCleanStaleSessions = null;
+        Log.setSessionContext(mComponentContextFixture.getTestDouble().getApplicationContext());
         MockitoAnnotations.initMocks(this);
     }
 
@@ -46,7 +44,6 @@
     public void tearDown() throws Exception {
         mComponentContextFixture = null;
         mMockitoHelper.tearDown();
-        Log.setTag(com.android.server.telecom.Log.TAG);
     }
 
     protected final void waitForHandlerAction(Handler h, long timeoutMillis) {
diff --git a/tests/src/com/android/server/telecom/tests/VideoCallTests.java b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
index 0319e81..4764e92 100644
--- a/tests/src/com/android/server/telecom/tests/VideoCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
@@ -25,7 +25,6 @@
 
 import com.android.server.telecom.CallAudioModeStateMachine;
 import com.android.server.telecom.CallAudioRouteStateMachine;
-import com.android.server.telecom.Log;
 
 import java.util.List;
 
diff --git a/tests/src/com/android/server/telecom/tests/VideoProviderTest.java b/tests/src/com/android/server/telecom/tests/VideoProviderTest.java
index 993679e..cca6446 100644
--- a/tests/src/com/android/server/telecom/tests/VideoProviderTest.java
+++ b/tests/src/com/android/server/telecom/tests/VideoProviderTest.java
@@ -16,8 +16,6 @@
 
 package com.android.server.telecom.tests;
 
-import com.android.server.telecom.Log;
-
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.Mockito;
@@ -25,21 +23,13 @@
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Camera;
 import android.graphics.SurfaceTexture;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
-import android.telecom.Call;
-import android.telecom.CallAudioState;
-import android.telecom.Connection;
 import android.telecom.Connection.VideoProvider;
 import android.telecom.InCallService;
 import android.telecom.InCallService.VideoCall;
-import android.telecom.ParcelableCall;
-import android.telecom.TelecomManager;
 import android.telecom.VideoCallImpl;
 import android.telecom.VideoProfile;
 import android.telecom.VideoProfile.CameraCapabilities;
@@ -50,7 +40,6 @@
 
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.RunnableFuture;
 import java.util.concurrent.TimeUnit;
 
 import static android.test.MoreAsserts.assertEquals;