Loading src/com/android/server/telecom/Analytics.java +228 −26 Original line number Diff line number Diff line Loading @@ -16,45 +16,154 @@ package com.android.server.telecom; import android.os.Parcelable; import android.telecom.ParcelableCallAnalytics; import android.telecom.DisconnectCause; import android.telecom.ParcelableCallAnalytics; import android.telecom.TelecomAnalytics; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.CallerInfo; import com.android.internal.util.IndentingPrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import static android.telecom.ParcelableCallAnalytics.AnalyticsEvent; import static android.telecom.TelecomAnalytics.SessionTiming; /** * A class that collects and stores data on how calls are being made, in order to * aggregate these into useful statistics. */ public class Analytics { 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); }}; 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, 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); }}; public static final Map<String, Integer> sLogEventTimingToAnalyticsEventTiming = new HashMap<String, Integer>() {{ put(Log.Events.Timings.ACCEPT_TIMING, ParcelableCallAnalytics.EventTiming.ACCEPT_TIMING); put(Log.Events.Timings.REJECT_TIMING, ParcelableCallAnalytics.EventTiming.REJECT_TIMING); put(Log.Events.Timings.DISCONNECT_TIMING, ParcelableCallAnalytics.EventTiming.DISCONNECT_TIMING); put(Log.Events.Timings.HOLD_TIMING, ParcelableCallAnalytics.EventTiming.HOLD_TIMING); put(Log.Events.Timings.UNHOLD_TIMING, ParcelableCallAnalytics.EventTiming.UNHOLD_TIMING); put(Log.Events.Timings.OUTGOING_TIME_TO_DIALING_TIMING, ParcelableCallAnalytics.EventTiming.OUTGOING_TIME_TO_DIALING_TIMING); put(Log.Events.Timings.BIND_CS_TIMING, ParcelableCallAnalytics.EventTiming.BIND_CS_TIMING); put(Log.Events.Timings.SCREENING_COMPLETED_TIMING, ParcelableCallAnalytics.EventTiming.SCREENING_COMPLETED_TIMING); put(Log.Events.Timings.DIRECT_TO_VM_FINISHED_TIMING, ParcelableCallAnalytics.EventTiming.DIRECT_TO_VM_FINISHED_TIMING); put(Log.Events.Timings.BLOCK_CHECK_FINISHED_TIMING, ParcelableCallAnalytics.EventTiming.BLOCK_CHECK_FINISHED_TIMING); put(Log.Events.Timings.FILTERING_COMPLETED_TIMING, ParcelableCallAnalytics.EventTiming.FILTERING_COMPLETED_TIMING); put(Log.Events.Timings.FILTERING_TIMED_OUT_TIMING, ParcelableCallAnalytics.EventTiming.FILTERING_TIMED_OUT_TIMING); }}; public static final Map<Integer, String> sSessionIdToLogSession = new HashMap<>(); static { for (Map.Entry<String, Integer> e : sLogSessionToSessionId.entrySet()) { sSessionIdToLogSession.put(e.getValue(), e.getKey()); } } public static class CallInfo { void setCallStartTime(long startTime) { public void setCallStartTime(long startTime) { } void setCallEndTime(long endTime) { public void setCallEndTime(long endTime) { } public void setCallIsAdditional(boolean isAdditional) { } void setCallIsAdditional(boolean isAdditional) { public void setCallIsInterrupted(boolean isInterrupted) { } void setCallIsInterrupted(boolean isInterrupted) { public void setCallDisconnectCause(DisconnectCause disconnectCause) { } void setCallDisconnectCause(DisconnectCause disconnectCause) { public void addCallTechnology(int callTechnology) { } void addCallTechnology(int callTechnology) { public void setCreatedFromExistingConnection(boolean createdFromExistingConnection) { } void setCreatedFromExistingConnection(boolean createdFromExistingConnection) { public void setCallConnectionService(String connectionServiceName) { } void setCallConnectionService(String connectionServiceName) { public void setCallEvents(Log.CallEventRecord records) { } } Loading Loading @@ -83,6 +192,8 @@ public class Analytics { public String connectionService; public boolean isEmergency = false; public Log.CallEventRecord callEvents; CallInfoImpl(String callId, int callDirection) { this.callId = callId; startTime = 0; Loading @@ -103,6 +214,7 @@ public class Analytics { this.createdFromExistingConnection = other.createdFromExistingConnection; this.connectionService = other.connectionService; this.isEmergency = other.isEmergency; this.callEvents = other.callEvents; if (other.callTerminationReason != null) { this.callTerminationReason = new DisconnectCause( Loading Loading @@ -166,6 +278,11 @@ public class Analytics { this.connectionService = connectionServiceName; } @Override public void setCallEvents(Log.CallEventRecord records) { this.callEvents = records; } @Override public String toString() { return "{\n" Loading @@ -185,6 +302,18 @@ public class Analytics { long callDuration = (endTime == 0 || startTime == 0) ? 0 : endTime - startTime; callDuration += (callDuration % MILLIS_IN_1_SECOND == 0) ? 0 : (MILLIS_IN_1_SECOND - callDuration % MILLIS_IN_1_SECOND); List<AnalyticsEvent> events; List<ParcelableCallAnalytics.EventTiming> timings; if (callEvents != null) { events = convertLogEventsToAnalyticsEvents(callEvents.getEvents()); timings = callEvents.extractEventTimings().stream() .map(Analytics::logEventTimingToAnalyticsEventTiming) .collect(Collectors.toList()); } else { events = Collections.emptyList(); timings = Collections.emptyList(); } return new ParcelableCallAnalytics( // rounds down to nearest 5 minute mark startTime - startTime % ParcelableCallAnalytics.MILLIS_IN_5_MINUTES, Loading @@ -198,7 +327,9 @@ public class Analytics { callTerminationReason.getCode(), isEmergency, connectionService, createdFromExistingConnection); createdFromExistingConnection, events, timings); } private String getCallDirectionString() { Loading Loading @@ -252,6 +383,16 @@ public class Analytics { private static final Object sLock = new Object(); // Coarse lock for all of analytics private static final Map<String, CallInfoImpl> sCallIdToInfo = new HashMap<>(); private static final List<SessionTiming> sSessionTimings = new LinkedList<>(); public static void addSessionTiming(String sessionName, long time) { if (sLogSessionToSessionId.containsKey(sessionName)) { synchronized (sLock) { sSessionTimings.add(new SessionTiming(sLogSessionToSessionId.get(sessionName), time)); } } } public static CallInfo initiateCallAnalytics(String callId, int direction) { Log.d(TAG, "Starting analytics for call " + callId); Loading @@ -262,26 +403,46 @@ public class Analytics { return callInfo; } public static ParcelableCallAnalytics[] dumpToParcelableAnalytics() { ParcelableCallAnalytics[] result; public static TelecomAnalytics dumpToParcelableAnalytics() { List<ParcelableCallAnalytics> calls = new LinkedList<>(); List<SessionTiming> sessionTimings = new LinkedList<>(); synchronized (sLock) { result = new ParcelableCallAnalytics[sCallIdToInfo.size()]; int idx = 0; for (CallInfoImpl entry : sCallIdToInfo.values()) { result[idx] = entry.toParcelableAnalytics(); idx++; } calls.addAll(sCallIdToInfo.values().stream() .map(CallInfoImpl::toParcelableAnalytics) .collect(Collectors.toList())); sessionTimings.addAll(sSessionTimings); sCallIdToInfo.clear(); sSessionTimings.clear(); } return result; return new TelecomAnalytics(sessionTimings, calls); } public static void dump(IndentingPrintWriter writer) { synchronized (sLock) { for (Map.Entry<String, CallInfoImpl> entry : sCallIdToInfo.entrySet()) { writer.printf("Call %s: ", entry.getKey()); writer.println(entry.getValue().toString()); int prefixLength = CallsManager.TELECOM_CALL_ID_PREFIX.length(); List<String> callIds = new ArrayList<>(sCallIdToInfo.keySet()); // Sort the analytics in increasing order of call IDs Collections.sort(callIds, (id1, id2) -> { int i1, i2; try { i1 = Integer.valueOf(id1.substring(prefixLength)); i2 = Integer.valueOf(id2.substring(prefixLength)); } catch (NumberFormatException e) { return 0; } return i1 - i2; }); for (String callId : callIds) { writer.printf("Call %s: ", callId); writer.println(sCallIdToInfo.get(callId).toString()); } Map<Integer, Double> averageTimings = SessionTiming.averageTimings(sSessionTimings); averageTimings.entrySet().stream() .filter(e -> sSessionIdToLogSession.containsKey(e.getKey())) .forEach(e -> writer.printf("%s: %.2f\n", sSessionIdToLogSession.get(e.getKey()), e.getValue())); } } Loading @@ -292,8 +453,9 @@ public class Analytics { } /** * Returns a deep copy of callIdToInfo that's safe to read/write without synchronization * Returns a copy of callIdToInfo. Use only for testing. */ @VisibleForTesting public static Map<String, CallInfoImpl> cloneData() { synchronized (sLock) { Map<String, CallInfoImpl> result = new HashMap<>(sCallIdToInfo.size()); Loading @@ -303,4 +465,44 @@ public class Analytics { return result; } } private static List<AnalyticsEvent> convertLogEventsToAnalyticsEvents( List<Log.CallEvent> logEvents) { long timeOfLastEvent = -1; ArrayList<AnalyticsEvent> events = new ArrayList<>(logEvents.size()); for (Log.CallEvent logEvent : logEvents) { if (sLogEventToAnalyticsEvent.containsKey(logEvent.eventId)) { int analyticsEventId = sLogEventToAnalyticsEvent.get(logEvent.eventId); long timeSinceLastEvent = timeOfLastEvent < 0 ? -1 : logEvent.time - timeOfLastEvent; events.add(new AnalyticsEvent( analyticsEventId, roundToOneSigFig(timeSinceLastEvent) )); timeOfLastEvent = logEvent.time; } } return events; } private static ParcelableCallAnalytics.EventTiming logEventTimingToAnalyticsEventTiming( Log.CallEventRecord.EventTiming logEventTiming) { int analyticsEventTimingName = sLogEventTimingToAnalyticsEventTiming.containsKey(logEventTiming.name) ? sLogEventTimingToAnalyticsEventTiming.get(logEventTiming.name) : ParcelableCallAnalytics.EventTiming.INVALID; return new ParcelableCallAnalytics.EventTiming(analyticsEventTimingName, (long) logEventTiming.time); } @VisibleForTesting public static long roundToOneSigFig(long val) { if (val == 0) { return val; } int logVal = (int) Math.floor(Math.log10(val < 0 ? -val : val)); double s = Math.pow(10, logVal); double dec = val / s; return (long) (Math.round(dec) * s); } } src/com/android/server/telecom/Call.java +3 −3 Original line number Diff line number Diff line Loading @@ -430,7 +430,6 @@ public class Call implements CreateConnectionResponse { maybeLoadCannedSmsResponses(); mAnalytics = new Analytics.CallInfo(); Log.event(this, Log.Events.CREATED); } /** Loading Loading @@ -501,6 +500,7 @@ public class Call implements CreateConnectionResponse { analyticsDirection = Analytics.UNKNOWN_DIRECTION; } mAnalytics = Analytics.initiateCallAnalytics(mId, analyticsDirection); Log.event(this, Log.Events.CREATED); } public Analytics.CallInfo getAnalytics() { Loading Loading @@ -1477,7 +1477,7 @@ public class Call implements CreateConnectionResponse { if (mConnectionService == null) { Log.w(this, "splitting from conference call without a connection service"); } else { Log.event(this, Log.Events.SPLIT_CONFERENCE); Log.event(this, Log.Events.SPLIT_FROM_CONFERENCE); mConnectionService.splitFromConference(this); } } Loading Loading @@ -1550,7 +1550,7 @@ public class Call implements CreateConnectionResponse { return; } Log.event(this, Log.Events.PULL); Log.event(this, Log.Events.REQUEST_PULL); mConnectionService.pullExternalCall(this); } Loading src/com/android/server/telecom/CallAudioRouteStateMachine.java +15 −5 Original line number Diff line number Diff line Loading @@ -107,6 +107,13 @@ public class CallAudioRouteStateMachine extends StateMachine { public static final int NO_FOCUS = 1; public static final int HAS_FOCUS = 2; 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); }}; private static final SparseArray<String> MESSAGE_CODE_TO_NAME = new SparseArray<String>() {{ put(CONNECT_WIRED_HEADSET, "CONNECT_WIRED_HEADSET"); put(DISCONNECT_WIRED_HEADSET, "DISCONNECT_WIRED_HEADSET"); Loading Loading @@ -1139,8 +1146,8 @@ public class CallAudioRouteStateMachine extends StateMachine { private void setMuteOn(boolean mute) { mIsMuted = mute; Log.event(mCallsManager.getForegroundCall(), Log.Events.MUTE, mute ? "on" : "off"); Log.event(mCallsManager.getForegroundCall(), mute ? Log.Events.MUTE : Log.Events.UNMUTE); if (mute != mAudioManager.isMicrophoneMute() && isInActiveState()) { IAudioService audio = mAudioServiceFactory.getAudioService(); Log.i(this, "changing microphone mute state to: %b [serviceIsNull=%b]", Loading Loading @@ -1192,10 +1199,13 @@ public class CallAudioRouteStateMachine extends StateMachine { private void setSystemAudioState(CallAudioState newCallAudioState, boolean force) { Log.i(this, "setSystemAudioState: changing from %s to %s", mLastKnownCallAudioState, newCallAudioState); Log.event(mCallsManager.getForegroundCall(), Log.Events.AUDIO_ROUTE, CallAudioState.audioRouteToString(newCallAudioState.getRoute())); if (force || !newCallAudioState.equals(mLastKnownCallAudioState)) { if (newCallAudioState.getRoute() != mLastKnownCallAudioState.getRoute()) { Log.event(mCallsManager.getForegroundCall(), AUDIO_ROUTE_TO_LOG_EVENT.get(newCallAudioState.getRoute(), Log.Events.AUDIO_ROUTE)); } mCallsManager.onCallAudioStateChanged(mLastKnownCallAudioState, newCallAudioState); updateAudioForForegroundCall(newCallAudioState); mLastKnownCallAudioState = newCallAudioState; Loading src/com/android/server/telecom/CallsManager.java +8 −2 Original line number Diff line number Diff line Loading @@ -779,10 +779,10 @@ public class CallsManager extends Call.ListenerBase false /* forceAttachToExistingConnection */, false /* isConference */ ); call.setInitiatingUser(initiatingUser); call.initAnalytics(); call.setInitiatingUser(initiatingUser); isReusedCall = false; } Loading Loading @@ -1165,13 +1165,19 @@ public class CallsManager extends Call.ListenerBase if (!mCalls.contains(call)) { Log.w(this, "Unknown call (%s) asked to be removed from hold", call); } else { boolean otherCallHeld = false; Log.d(this, "unholding call: (%s)", call); for (Call c : mCalls) { // 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); c.hold(); } } if (otherCallHeld) { Log.event(call, Log.Events.SWAP); } call.unhold(); } } Loading src/com/android/server/telecom/ConnectionServiceWrapper.java +9 −9 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void handleCreateConnectionComplete(String callId, ConnectionRequest request, ParcelableConnection connection) { Log.startSession("CSW.hCCC"); Log.startSession(Log.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading @@ -82,7 +82,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void setActive(String callId) { Log.startSession("CSW.sA"); Log.startSession(Log.Sessions.CSW_SET_ACTIVE); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading @@ -102,7 +102,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void setRinging(String callId) { Log.startSession("CSW.sR"); Log.startSession(Log.Sessions.CSW_SET_RINGING); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading Loading @@ -140,7 +140,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void setDialing(String callId) { Log.startSession("CSW.sD"); Log.startSession(Log.Sessions.CSW_SET_DIALING); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading @@ -160,7 +160,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void setDisconnected(String callId, DisconnectCause disconnectCause) { Log.startSession("CSW.sD"); Log.startSession(Log.Sessions.CSW_SET_DISCONNECTED); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading @@ -181,7 +181,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void setOnHold(String callId) { Log.startSession("CSW.sOH"); Log.startSession(Log.Sessions.CSW_SET_ON_HOLD); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading Loading @@ -221,7 +221,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void removeCall(String callId) { Log.startSession("CSW.rC"); Log.startSession(Log.Sessions.CSW_REMOVE_CALL); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading Loading @@ -283,7 +283,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void setIsConferenced(String callId, String conferenceCallId) { Log.startSession("CSW.sIC"); Log.startSession(Log.Sessions.CSW_SET_IS_CONFERENCED); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading Loading @@ -332,7 +332,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void addConferenceCall(String callId, ParcelableConference parcelableConference) { Log.startSession("CSW.aCC"); Log.startSession(Log.Sessions.CSW_ADD_CONFERENCE_CALL); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading Loading
src/com/android/server/telecom/Analytics.java +228 −26 Original line number Diff line number Diff line Loading @@ -16,45 +16,154 @@ package com.android.server.telecom; import android.os.Parcelable; import android.telecom.ParcelableCallAnalytics; import android.telecom.DisconnectCause; import android.telecom.ParcelableCallAnalytics; import android.telecom.TelecomAnalytics; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.CallerInfo; import com.android.internal.util.IndentingPrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import static android.telecom.ParcelableCallAnalytics.AnalyticsEvent; import static android.telecom.TelecomAnalytics.SessionTiming; /** * A class that collects and stores data on how calls are being made, in order to * aggregate these into useful statistics. */ public class Analytics { 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); }}; 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, 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); }}; public static final Map<String, Integer> sLogEventTimingToAnalyticsEventTiming = new HashMap<String, Integer>() {{ put(Log.Events.Timings.ACCEPT_TIMING, ParcelableCallAnalytics.EventTiming.ACCEPT_TIMING); put(Log.Events.Timings.REJECT_TIMING, ParcelableCallAnalytics.EventTiming.REJECT_TIMING); put(Log.Events.Timings.DISCONNECT_TIMING, ParcelableCallAnalytics.EventTiming.DISCONNECT_TIMING); put(Log.Events.Timings.HOLD_TIMING, ParcelableCallAnalytics.EventTiming.HOLD_TIMING); put(Log.Events.Timings.UNHOLD_TIMING, ParcelableCallAnalytics.EventTiming.UNHOLD_TIMING); put(Log.Events.Timings.OUTGOING_TIME_TO_DIALING_TIMING, ParcelableCallAnalytics.EventTiming.OUTGOING_TIME_TO_DIALING_TIMING); put(Log.Events.Timings.BIND_CS_TIMING, ParcelableCallAnalytics.EventTiming.BIND_CS_TIMING); put(Log.Events.Timings.SCREENING_COMPLETED_TIMING, ParcelableCallAnalytics.EventTiming.SCREENING_COMPLETED_TIMING); put(Log.Events.Timings.DIRECT_TO_VM_FINISHED_TIMING, ParcelableCallAnalytics.EventTiming.DIRECT_TO_VM_FINISHED_TIMING); put(Log.Events.Timings.BLOCK_CHECK_FINISHED_TIMING, ParcelableCallAnalytics.EventTiming.BLOCK_CHECK_FINISHED_TIMING); put(Log.Events.Timings.FILTERING_COMPLETED_TIMING, ParcelableCallAnalytics.EventTiming.FILTERING_COMPLETED_TIMING); put(Log.Events.Timings.FILTERING_TIMED_OUT_TIMING, ParcelableCallAnalytics.EventTiming.FILTERING_TIMED_OUT_TIMING); }}; public static final Map<Integer, String> sSessionIdToLogSession = new HashMap<>(); static { for (Map.Entry<String, Integer> e : sLogSessionToSessionId.entrySet()) { sSessionIdToLogSession.put(e.getValue(), e.getKey()); } } public static class CallInfo { void setCallStartTime(long startTime) { public void setCallStartTime(long startTime) { } void setCallEndTime(long endTime) { public void setCallEndTime(long endTime) { } public void setCallIsAdditional(boolean isAdditional) { } void setCallIsAdditional(boolean isAdditional) { public void setCallIsInterrupted(boolean isInterrupted) { } void setCallIsInterrupted(boolean isInterrupted) { public void setCallDisconnectCause(DisconnectCause disconnectCause) { } void setCallDisconnectCause(DisconnectCause disconnectCause) { public void addCallTechnology(int callTechnology) { } void addCallTechnology(int callTechnology) { public void setCreatedFromExistingConnection(boolean createdFromExistingConnection) { } void setCreatedFromExistingConnection(boolean createdFromExistingConnection) { public void setCallConnectionService(String connectionServiceName) { } void setCallConnectionService(String connectionServiceName) { public void setCallEvents(Log.CallEventRecord records) { } } Loading Loading @@ -83,6 +192,8 @@ public class Analytics { public String connectionService; public boolean isEmergency = false; public Log.CallEventRecord callEvents; CallInfoImpl(String callId, int callDirection) { this.callId = callId; startTime = 0; Loading @@ -103,6 +214,7 @@ public class Analytics { this.createdFromExistingConnection = other.createdFromExistingConnection; this.connectionService = other.connectionService; this.isEmergency = other.isEmergency; this.callEvents = other.callEvents; if (other.callTerminationReason != null) { this.callTerminationReason = new DisconnectCause( Loading Loading @@ -166,6 +278,11 @@ public class Analytics { this.connectionService = connectionServiceName; } @Override public void setCallEvents(Log.CallEventRecord records) { this.callEvents = records; } @Override public String toString() { return "{\n" Loading @@ -185,6 +302,18 @@ public class Analytics { long callDuration = (endTime == 0 || startTime == 0) ? 0 : endTime - startTime; callDuration += (callDuration % MILLIS_IN_1_SECOND == 0) ? 0 : (MILLIS_IN_1_SECOND - callDuration % MILLIS_IN_1_SECOND); List<AnalyticsEvent> events; List<ParcelableCallAnalytics.EventTiming> timings; if (callEvents != null) { events = convertLogEventsToAnalyticsEvents(callEvents.getEvents()); timings = callEvents.extractEventTimings().stream() .map(Analytics::logEventTimingToAnalyticsEventTiming) .collect(Collectors.toList()); } else { events = Collections.emptyList(); timings = Collections.emptyList(); } return new ParcelableCallAnalytics( // rounds down to nearest 5 minute mark startTime - startTime % ParcelableCallAnalytics.MILLIS_IN_5_MINUTES, Loading @@ -198,7 +327,9 @@ public class Analytics { callTerminationReason.getCode(), isEmergency, connectionService, createdFromExistingConnection); createdFromExistingConnection, events, timings); } private String getCallDirectionString() { Loading Loading @@ -252,6 +383,16 @@ public class Analytics { private static final Object sLock = new Object(); // Coarse lock for all of analytics private static final Map<String, CallInfoImpl> sCallIdToInfo = new HashMap<>(); private static final List<SessionTiming> sSessionTimings = new LinkedList<>(); public static void addSessionTiming(String sessionName, long time) { if (sLogSessionToSessionId.containsKey(sessionName)) { synchronized (sLock) { sSessionTimings.add(new SessionTiming(sLogSessionToSessionId.get(sessionName), time)); } } } public static CallInfo initiateCallAnalytics(String callId, int direction) { Log.d(TAG, "Starting analytics for call " + callId); Loading @@ -262,26 +403,46 @@ public class Analytics { return callInfo; } public static ParcelableCallAnalytics[] dumpToParcelableAnalytics() { ParcelableCallAnalytics[] result; public static TelecomAnalytics dumpToParcelableAnalytics() { List<ParcelableCallAnalytics> calls = new LinkedList<>(); List<SessionTiming> sessionTimings = new LinkedList<>(); synchronized (sLock) { result = new ParcelableCallAnalytics[sCallIdToInfo.size()]; int idx = 0; for (CallInfoImpl entry : sCallIdToInfo.values()) { result[idx] = entry.toParcelableAnalytics(); idx++; } calls.addAll(sCallIdToInfo.values().stream() .map(CallInfoImpl::toParcelableAnalytics) .collect(Collectors.toList())); sessionTimings.addAll(sSessionTimings); sCallIdToInfo.clear(); sSessionTimings.clear(); } return result; return new TelecomAnalytics(sessionTimings, calls); } public static void dump(IndentingPrintWriter writer) { synchronized (sLock) { for (Map.Entry<String, CallInfoImpl> entry : sCallIdToInfo.entrySet()) { writer.printf("Call %s: ", entry.getKey()); writer.println(entry.getValue().toString()); int prefixLength = CallsManager.TELECOM_CALL_ID_PREFIX.length(); List<String> callIds = new ArrayList<>(sCallIdToInfo.keySet()); // Sort the analytics in increasing order of call IDs Collections.sort(callIds, (id1, id2) -> { int i1, i2; try { i1 = Integer.valueOf(id1.substring(prefixLength)); i2 = Integer.valueOf(id2.substring(prefixLength)); } catch (NumberFormatException e) { return 0; } return i1 - i2; }); for (String callId : callIds) { writer.printf("Call %s: ", callId); writer.println(sCallIdToInfo.get(callId).toString()); } Map<Integer, Double> averageTimings = SessionTiming.averageTimings(sSessionTimings); averageTimings.entrySet().stream() .filter(e -> sSessionIdToLogSession.containsKey(e.getKey())) .forEach(e -> writer.printf("%s: %.2f\n", sSessionIdToLogSession.get(e.getKey()), e.getValue())); } } Loading @@ -292,8 +453,9 @@ public class Analytics { } /** * Returns a deep copy of callIdToInfo that's safe to read/write without synchronization * Returns a copy of callIdToInfo. Use only for testing. */ @VisibleForTesting public static Map<String, CallInfoImpl> cloneData() { synchronized (sLock) { Map<String, CallInfoImpl> result = new HashMap<>(sCallIdToInfo.size()); Loading @@ -303,4 +465,44 @@ public class Analytics { return result; } } private static List<AnalyticsEvent> convertLogEventsToAnalyticsEvents( List<Log.CallEvent> logEvents) { long timeOfLastEvent = -1; ArrayList<AnalyticsEvent> events = new ArrayList<>(logEvents.size()); for (Log.CallEvent logEvent : logEvents) { if (sLogEventToAnalyticsEvent.containsKey(logEvent.eventId)) { int analyticsEventId = sLogEventToAnalyticsEvent.get(logEvent.eventId); long timeSinceLastEvent = timeOfLastEvent < 0 ? -1 : logEvent.time - timeOfLastEvent; events.add(new AnalyticsEvent( analyticsEventId, roundToOneSigFig(timeSinceLastEvent) )); timeOfLastEvent = logEvent.time; } } return events; } private static ParcelableCallAnalytics.EventTiming logEventTimingToAnalyticsEventTiming( Log.CallEventRecord.EventTiming logEventTiming) { int analyticsEventTimingName = sLogEventTimingToAnalyticsEventTiming.containsKey(logEventTiming.name) ? sLogEventTimingToAnalyticsEventTiming.get(logEventTiming.name) : ParcelableCallAnalytics.EventTiming.INVALID; return new ParcelableCallAnalytics.EventTiming(analyticsEventTimingName, (long) logEventTiming.time); } @VisibleForTesting public static long roundToOneSigFig(long val) { if (val == 0) { return val; } int logVal = (int) Math.floor(Math.log10(val < 0 ? -val : val)); double s = Math.pow(10, logVal); double dec = val / s; return (long) (Math.round(dec) * s); } }
src/com/android/server/telecom/Call.java +3 −3 Original line number Diff line number Diff line Loading @@ -430,7 +430,6 @@ public class Call implements CreateConnectionResponse { maybeLoadCannedSmsResponses(); mAnalytics = new Analytics.CallInfo(); Log.event(this, Log.Events.CREATED); } /** Loading Loading @@ -501,6 +500,7 @@ public class Call implements CreateConnectionResponse { analyticsDirection = Analytics.UNKNOWN_DIRECTION; } mAnalytics = Analytics.initiateCallAnalytics(mId, analyticsDirection); Log.event(this, Log.Events.CREATED); } public Analytics.CallInfo getAnalytics() { Loading Loading @@ -1477,7 +1477,7 @@ public class Call implements CreateConnectionResponse { if (mConnectionService == null) { Log.w(this, "splitting from conference call without a connection service"); } else { Log.event(this, Log.Events.SPLIT_CONFERENCE); Log.event(this, Log.Events.SPLIT_FROM_CONFERENCE); mConnectionService.splitFromConference(this); } } Loading Loading @@ -1550,7 +1550,7 @@ public class Call implements CreateConnectionResponse { return; } Log.event(this, Log.Events.PULL); Log.event(this, Log.Events.REQUEST_PULL); mConnectionService.pullExternalCall(this); } Loading
src/com/android/server/telecom/CallAudioRouteStateMachine.java +15 −5 Original line number Diff line number Diff line Loading @@ -107,6 +107,13 @@ public class CallAudioRouteStateMachine extends StateMachine { public static final int NO_FOCUS = 1; public static final int HAS_FOCUS = 2; 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); }}; private static final SparseArray<String> MESSAGE_CODE_TO_NAME = new SparseArray<String>() {{ put(CONNECT_WIRED_HEADSET, "CONNECT_WIRED_HEADSET"); put(DISCONNECT_WIRED_HEADSET, "DISCONNECT_WIRED_HEADSET"); Loading Loading @@ -1139,8 +1146,8 @@ public class CallAudioRouteStateMachine extends StateMachine { private void setMuteOn(boolean mute) { mIsMuted = mute; Log.event(mCallsManager.getForegroundCall(), Log.Events.MUTE, mute ? "on" : "off"); Log.event(mCallsManager.getForegroundCall(), mute ? Log.Events.MUTE : Log.Events.UNMUTE); if (mute != mAudioManager.isMicrophoneMute() && isInActiveState()) { IAudioService audio = mAudioServiceFactory.getAudioService(); Log.i(this, "changing microphone mute state to: %b [serviceIsNull=%b]", Loading Loading @@ -1192,10 +1199,13 @@ public class CallAudioRouteStateMachine extends StateMachine { private void setSystemAudioState(CallAudioState newCallAudioState, boolean force) { Log.i(this, "setSystemAudioState: changing from %s to %s", mLastKnownCallAudioState, newCallAudioState); Log.event(mCallsManager.getForegroundCall(), Log.Events.AUDIO_ROUTE, CallAudioState.audioRouteToString(newCallAudioState.getRoute())); if (force || !newCallAudioState.equals(mLastKnownCallAudioState)) { if (newCallAudioState.getRoute() != mLastKnownCallAudioState.getRoute()) { Log.event(mCallsManager.getForegroundCall(), AUDIO_ROUTE_TO_LOG_EVENT.get(newCallAudioState.getRoute(), Log.Events.AUDIO_ROUTE)); } mCallsManager.onCallAudioStateChanged(mLastKnownCallAudioState, newCallAudioState); updateAudioForForegroundCall(newCallAudioState); mLastKnownCallAudioState = newCallAudioState; Loading
src/com/android/server/telecom/CallsManager.java +8 −2 Original line number Diff line number Diff line Loading @@ -779,10 +779,10 @@ public class CallsManager extends Call.ListenerBase false /* forceAttachToExistingConnection */, false /* isConference */ ); call.setInitiatingUser(initiatingUser); call.initAnalytics(); call.setInitiatingUser(initiatingUser); isReusedCall = false; } Loading Loading @@ -1165,13 +1165,19 @@ public class CallsManager extends Call.ListenerBase if (!mCalls.contains(call)) { Log.w(this, "Unknown call (%s) asked to be removed from hold", call); } else { boolean otherCallHeld = false; Log.d(this, "unholding call: (%s)", call); for (Call c : mCalls) { // 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); c.hold(); } } if (otherCallHeld) { Log.event(call, Log.Events.SWAP); } call.unhold(); } } Loading
src/com/android/server/telecom/ConnectionServiceWrapper.java +9 −9 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void handleCreateConnectionComplete(String callId, ConnectionRequest request, ParcelableConnection connection) { Log.startSession("CSW.hCCC"); Log.startSession(Log.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading @@ -82,7 +82,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void setActive(String callId) { Log.startSession("CSW.sA"); Log.startSession(Log.Sessions.CSW_SET_ACTIVE); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading @@ -102,7 +102,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void setRinging(String callId) { Log.startSession("CSW.sR"); Log.startSession(Log.Sessions.CSW_SET_RINGING); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading Loading @@ -140,7 +140,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void setDialing(String callId) { Log.startSession("CSW.sD"); Log.startSession(Log.Sessions.CSW_SET_DIALING); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading @@ -160,7 +160,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void setDisconnected(String callId, DisconnectCause disconnectCause) { Log.startSession("CSW.sD"); Log.startSession(Log.Sessions.CSW_SET_DISCONNECTED); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading @@ -181,7 +181,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void setOnHold(String callId) { Log.startSession("CSW.sOH"); Log.startSession(Log.Sessions.CSW_SET_ON_HOLD); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading Loading @@ -221,7 +221,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void removeCall(String callId) { Log.startSession("CSW.rC"); Log.startSession(Log.Sessions.CSW_REMOVE_CALL); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading Loading @@ -283,7 +283,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void setIsConferenced(String callId, String conferenceCallId) { Log.startSession("CSW.sIC"); Log.startSession(Log.Sessions.CSW_SET_IS_CONFERENCED); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading Loading @@ -332,7 +332,7 @@ public class ConnectionServiceWrapper extends ServiceBinder { @Override public void addConferenceCall(String callId, ParcelableConference parcelableConference) { Log.startSession("CSW.aCC"); Log.startSession(Log.Sessions.CSW_ADD_CONFERENCE_CALL); long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { Loading