13258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu/* 23258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu * Copyright (C) 2015 The Android Open Source Project 33258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu * 43258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu * Licensed under the Apache License, Version 2.0 (the "License"); 53258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu * you may not use this file except in compliance with the License. 63258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu * You may obtain a copy of the License at 73258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu * 83258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu * http://www.apache.org/licenses/LICENSE-2.0 93258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu * 103258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu * Unless required by applicable law or agreed to in writing, software 113258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu * distributed under the License is distributed on an "AS IS" BASIS, 123258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu * See the License for the specific language governing permissions and 143258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu * limitations under the License 153258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu */ 163258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 173258720f5526f766aa26c19cf01b32ac20d19d1dHall Liupackage com.android.server.telecom; 183258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 19d7fe686253f2135a948cafc776aa25db645ec27eHall Liuimport android.telecom.Connection; 203258720f5526f766aa26c19cf01b32ac20d19d1dHall Liuimport android.telecom.DisconnectCause; 21a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebingerimport android.telecom.Logging.EventManager; 22874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liuimport android.telecom.ParcelableCallAnalytics; 23874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liuimport android.telecom.TelecomAnalytics; 242f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liuimport android.util.Base64; 25a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebingerimport android.telecom.Log; 263258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 273258720f5526f766aa26c19cf01b32ac20d19d1dHall Liuimport com.android.internal.annotations.VisibleForTesting; 283258720f5526f766aa26c19cf01b32ac20d19d1dHall Liuimport com.android.internal.util.IndentingPrintWriter; 2983e882836bea5ae11f21dd619dd9ae3a2e0c12e3Tamas Berghammerimport com.android.server.telecom.nano.TelecomLogClass; 303258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 312f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liuimport java.io.PrintWriter; 32874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liuimport java.util.ArrayList; 332f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liuimport java.util.Arrays; 34874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liuimport java.util.Collections; 353258720f5526f766aa26c19cf01b32ac20d19d1dHall Liuimport java.util.HashMap; 36874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liuimport java.util.LinkedList; 37874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liuimport java.util.List; 383258720f5526f766aa26c19cf01b32ac20d19d1dHall Liuimport java.util.Map; 39d93b9ececca0fb8a2cc63858ce59012eb6fc17e9Hall Liuimport java.util.PriorityQueue; 40874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liuimport java.util.stream.Collectors; 41874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu 42874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liuimport static android.telecom.ParcelableCallAnalytics.AnalyticsEvent; 43874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liuimport static android.telecom.TelecomAnalytics.SessionTiming; 443258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 453258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu/** 463258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu * A class that collects and stores data on how calls are being made, in order to 473258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu * aggregate these into useful statistics. 483258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu */ 493258720f5526f766aa26c19cf01b32ac20d19d1dHall Liupublic class Analytics { 502f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu public static final String ANALYTICS_DUMPSYS_ARG = "analytics"; 512f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu private static final String CLEAR_ANALYTICS_ARG = "clear"; 522f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu 53874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu public static final Map<String, Integer> sLogEventToAnalyticsEvent = 54874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu new HashMap<String, Integer>() {{ 55a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.SET_SELECT_PHONE_ACCOUNT, 56a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger AnalyticsEvent.SET_SELECT_PHONE_ACCOUNT); 57a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.REQUEST_HOLD, AnalyticsEvent.REQUEST_HOLD); 58a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.REQUEST_UNHOLD, AnalyticsEvent.REQUEST_UNHOLD); 59a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.SWAP, AnalyticsEvent.SWAP); 60a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.SKIP_RINGING, AnalyticsEvent.SKIP_RINGING); 61a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.CONFERENCE_WITH, AnalyticsEvent.CONFERENCE_WITH); 62a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.SPLIT_FROM_CONFERENCE, AnalyticsEvent.SPLIT_CONFERENCE); 63a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.SET_PARENT, AnalyticsEvent.SET_PARENT); 64a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.MUTE, AnalyticsEvent.MUTE); 65a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.UNMUTE, AnalyticsEvent.UNMUTE); 66a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.AUDIO_ROUTE_BT, AnalyticsEvent.AUDIO_ROUTE_BT); 67a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.AUDIO_ROUTE_EARPIECE, AnalyticsEvent.AUDIO_ROUTE_EARPIECE); 68a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.AUDIO_ROUTE_HEADSET, AnalyticsEvent.AUDIO_ROUTE_HEADSET); 69a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.AUDIO_ROUTE_SPEAKER, AnalyticsEvent.AUDIO_ROUTE_SPEAKER); 70a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.SILENCE, AnalyticsEvent.SILENCE); 71a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.SCREENING_COMPLETED, AnalyticsEvent.SCREENING_COMPLETED); 72a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.BLOCK_CHECK_FINISHED, AnalyticsEvent.BLOCK_CHECK_FINISHED); 73a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.DIRECT_TO_VM_FINISHED, AnalyticsEvent.DIRECT_TO_VM_FINISHED); 74a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.REMOTELY_HELD, AnalyticsEvent.REMOTELY_HELD); 75a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.REMOTELY_UNHELD, AnalyticsEvent.REMOTELY_UNHELD); 76a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.REQUEST_PULL, AnalyticsEvent.REQUEST_PULL); 77a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.REQUEST_ACCEPT, AnalyticsEvent.REQUEST_ACCEPT); 78a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.REQUEST_REJECT, AnalyticsEvent.REQUEST_REJECT); 79a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.SET_ACTIVE, AnalyticsEvent.SET_ACTIVE); 80a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.SET_DISCONNECTED, AnalyticsEvent.SET_DISCONNECTED); 81a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.SET_HOLD, AnalyticsEvent.SET_HOLD); 82a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.SET_DIALING, AnalyticsEvent.SET_DIALING); 83a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.START_CONNECTION, AnalyticsEvent.START_CONNECTION); 84a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.BIND_CS, AnalyticsEvent.BIND_CS); 85a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.CS_BOUND, AnalyticsEvent.CS_BOUND); 86a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.SCREENING_SENT, AnalyticsEvent.SCREENING_SENT); 87a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.DIRECT_TO_VM_INITIATED, AnalyticsEvent.DIRECT_TO_VM_INITIATED); 88a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.BLOCK_CHECK_INITIATED, AnalyticsEvent.BLOCK_CHECK_INITIATED); 89a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.FILTERING_INITIATED, AnalyticsEvent.FILTERING_INITIATED); 90a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.FILTERING_COMPLETED, AnalyticsEvent.FILTERING_COMPLETED); 91a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.FILTERING_TIMED_OUT, AnalyticsEvent.FILTERING_TIMED_OUT); 92874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu }}; 93874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu 94874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu public static final Map<String, Integer> sLogSessionToSessionId = 95874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu new HashMap<String, Integer> () {{ 96a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.ICA_ANSWER_CALL, SessionTiming.ICA_ANSWER_CALL); 97a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.ICA_REJECT_CALL, SessionTiming.ICA_REJECT_CALL); 98a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.ICA_DISCONNECT_CALL, SessionTiming.ICA_DISCONNECT_CALL); 99a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.ICA_HOLD_CALL, SessionTiming.ICA_HOLD_CALL); 100a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.ICA_UNHOLD_CALL, SessionTiming.ICA_UNHOLD_CALL); 101a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.ICA_MUTE, SessionTiming.ICA_MUTE); 102a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.ICA_SET_AUDIO_ROUTE, SessionTiming.ICA_SET_AUDIO_ROUTE); 103a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.ICA_CONFERENCE, SessionTiming.ICA_CONFERENCE); 104a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE, 105874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu SessionTiming.CSW_HANDLE_CREATE_CONNECTION_COMPLETE); 106a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.CSW_SET_ACTIVE, SessionTiming.CSW_SET_ACTIVE); 107a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.CSW_SET_RINGING, SessionTiming.CSW_SET_RINGING); 108a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.CSW_SET_DIALING, SessionTiming.CSW_SET_DIALING); 109a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.CSW_SET_DISCONNECTED, SessionTiming.CSW_SET_DISCONNECTED); 110a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.CSW_SET_ON_HOLD, SessionTiming.CSW_SET_ON_HOLD); 111a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.CSW_REMOVE_CALL, SessionTiming.CSW_REMOVE_CALL); 112a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.CSW_SET_IS_CONFERENCED, SessionTiming.CSW_SET_IS_CONFERENCED); 113a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Sessions.CSW_ADD_CONFERENCE_CALL, 114a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger SessionTiming.CSW_ADD_CONFERENCE_CALL); 115874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu 116874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu }}; 117874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu 118874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu public static final Map<String, Integer> sLogEventTimingToAnalyticsEventTiming = 119874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu new HashMap<String, Integer>() {{ 120a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.Timings.ACCEPT_TIMING, 121874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu ParcelableCallAnalytics.EventTiming.ACCEPT_TIMING); 122a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.Timings.REJECT_TIMING, 123874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu ParcelableCallAnalytics.EventTiming.REJECT_TIMING); 124a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.Timings.DISCONNECT_TIMING, 125874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu ParcelableCallAnalytics.EventTiming.DISCONNECT_TIMING); 126a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.Timings.HOLD_TIMING, 127874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu ParcelableCallAnalytics.EventTiming.HOLD_TIMING); 128a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.Timings.UNHOLD_TIMING, 129874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu ParcelableCallAnalytics.EventTiming.UNHOLD_TIMING); 130a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.Timings.OUTGOING_TIME_TO_DIALING_TIMING, 131874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu ParcelableCallAnalytics.EventTiming.OUTGOING_TIME_TO_DIALING_TIMING); 132a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.Timings.BIND_CS_TIMING, 133874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu ParcelableCallAnalytics.EventTiming.BIND_CS_TIMING); 134a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.Timings.SCREENING_COMPLETED_TIMING, 135874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu ParcelableCallAnalytics.EventTiming.SCREENING_COMPLETED_TIMING); 136a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.Timings.DIRECT_TO_VM_FINISHED_TIMING, 137874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu ParcelableCallAnalytics.EventTiming.DIRECT_TO_VM_FINISHED_TIMING); 138a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.Timings.BLOCK_CHECK_FINISHED_TIMING, 139874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu ParcelableCallAnalytics.EventTiming.BLOCK_CHECK_FINISHED_TIMING); 140a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.Timings.FILTERING_COMPLETED_TIMING, 141874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu ParcelableCallAnalytics.EventTiming.FILTERING_COMPLETED_TIMING); 142a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger put(LogUtils.Events.Timings.FILTERING_TIMED_OUT_TIMING, 143874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu ParcelableCallAnalytics.EventTiming.FILTERING_TIMED_OUT_TIMING); 144874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu }}; 145874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu 146874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu public static final Map<Integer, String> sSessionIdToLogSession = new HashMap<>(); 147874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu static { 148874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu for (Map.Entry<String, Integer> e : sLogSessionToSessionId.entrySet()) { 149874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu sSessionIdToLogSession.put(e.getValue(), e.getKey()); 1503258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 151874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu } 1523258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 153874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu public static class CallInfo { 154874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu public void setCallStartTime(long startTime) { 1553258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 1563258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 157874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu public void setCallEndTime(long endTime) { 1583258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 1593258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 160874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu public void setCallIsAdditional(boolean isAdditional) { 1613258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 1623258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 163874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu public void setCallIsInterrupted(boolean isInterrupted) { 1643258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 1653258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 166874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu public void setCallDisconnectCause(DisconnectCause disconnectCause) { 1673258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 1683258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 169874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu public void addCallTechnology(int callTechnology) { 1703258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 1713258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 172874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu public void setCreatedFromExistingConnection(boolean createdFromExistingConnection) { 173874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu } 174874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu 175874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu public void setCallConnectionService(String connectionServiceName) { 176874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu } 177874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu 178a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger public void setCallEvents(EventManager.EventRecord records) { 1793258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 1804640c4fc55ca4118351330d68684ca9989661ccdHall Liu 1814640c4fc55ca4118351330d68684ca9989661ccdHall Liu public void setCallIsVideo(boolean isVideo) { 1824640c4fc55ca4118351330d68684ca9989661ccdHall Liu } 1834640c4fc55ca4118351330d68684ca9989661ccdHall Liu 1844640c4fc55ca4118351330d68684ca9989661ccdHall Liu public void addVideoEvent(int eventId, int videoState) { 1854640c4fc55ca4118351330d68684ca9989661ccdHall Liu } 1869d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu 1879d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu public void addInCallService(String serviceName, int type) { 1889d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu } 189d7fe686253f2135a948cafc776aa25db645ec27eHall Liu 190d7fe686253f2135a948cafc776aa25db645ec27eHall Liu public void addCallProperties(int properties) { 191d7fe686253f2135a948cafc776aa25db645ec27eHall Liu } 1923258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 1933258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 1943258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu /** 1953258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu * A class that holds data associated with a call. 1963258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu */ 1973258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu @VisibleForTesting 1983258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public static class CallInfoImpl extends CallInfo { 1993258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public String callId; 2003258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public long startTime; // start time in milliseconds since the epoch. 0 if not yet set. 2013258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public long endTime; // end time in milliseconds since the epoch. 0 if not yet set. 2023258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public int callDirection; // one of UNKNOWN_DIRECTION, INCOMING_DIRECTION, 2033258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu // or OUTGOING_DIRECTION. 2043258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public boolean isAdditionalCall = false; // true if the call came in while another call was 2053258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu // in progress or if the user dialed this call 2063258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu // while in the middle of another call. 2073258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public boolean isInterrupted = false; // true if the call was interrupted by an incoming 2083258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu // or outgoing call. 2093258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public int callTechnologies; // bitmask denoting which technologies a call used. 2103258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 2113258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu // true if the Telecom Call object was created from an existing connection via 2123258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu // CallsManager#createCallForExistingConnection, for example, by ImsConference. 2133258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public boolean createdFromExistingConnection = false; 2143258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 2153258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public DisconnectCause callTerminationReason; 2163258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public String connectionService; 2173258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public boolean isEmergency = false; 2183258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 219a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger public EventManager.EventRecord callEvents; 220874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu 2214640c4fc55ca4118351330d68684ca9989661ccdHall Liu public boolean isVideo = false; 2222f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu public List<TelecomLogClass.VideoEvent> videoEvents; 2239d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu public List<TelecomLogClass.InCallServiceInfo> inCallServiceInfos; 224d7fe686253f2135a948cafc776aa25db645ec27eHall Liu public int callProperties = 0; 225d7fe686253f2135a948cafc776aa25db645ec27eHall Liu 2264640c4fc55ca4118351330d68684ca9989661ccdHall Liu private long mTimeOfLastVideoEvent = -1; 2274640c4fc55ca4118351330d68684ca9989661ccdHall Liu 2283258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu CallInfoImpl(String callId, int callDirection) { 2293258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.callId = callId; 2303258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu startTime = 0; 2313258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu endTime = 0; 2323258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.callDirection = callDirection; 2333258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu callTechnologies = 0; 2343258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu connectionService = ""; 2354640c4fc55ca4118351330d68684ca9989661ccdHall Liu videoEvents = new LinkedList<>(); 2369d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu inCallServiceInfos = new LinkedList<>(); 2373258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 2383258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 2393258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu CallInfoImpl(CallInfoImpl other) { 2403258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.callId = other.callId; 2413258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.startTime = other.startTime; 2423258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.endTime = other.endTime; 2433258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.callDirection = other.callDirection; 2443258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.isAdditionalCall = other.isAdditionalCall; 2453258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.isInterrupted = other.isInterrupted; 2463258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.callTechnologies = other.callTechnologies; 2473258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.createdFromExistingConnection = other.createdFromExistingConnection; 2483258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.connectionService = other.connectionService; 2493258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.isEmergency = other.isEmergency; 250874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu this.callEvents = other.callEvents; 2514640c4fc55ca4118351330d68684ca9989661ccdHall Liu this.isVideo = other.isVideo; 2524640c4fc55ca4118351330d68684ca9989661ccdHall Liu this.videoEvents = other.videoEvents; 253d7fe686253f2135a948cafc776aa25db645ec27eHall Liu this.callProperties = other.callProperties; 2543258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 2553258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu if (other.callTerminationReason != null) { 2563258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.callTerminationReason = new DisconnectCause( 2573258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu other.callTerminationReason.getCode(), 2583258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu other.callTerminationReason.getLabel(), 2593258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu other.callTerminationReason.getDescription(), 2603258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu other.callTerminationReason.getReason(), 2613258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu other.callTerminationReason.getTone()); 2623258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } else { 2633258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.callTerminationReason = null; 2643258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 2653258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 2663258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 2673258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu @Override 2683258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public void setCallStartTime(long startTime) { 2693258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu Log.d(TAG, "setting startTime for call " + callId + " to " + startTime); 2703258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.startTime = startTime; 2713258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 2723258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 2733258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu @Override 2743258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public void setCallEndTime(long endTime) { 2753258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu Log.d(TAG, "setting endTime for call " + callId + " to " + endTime); 2763258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.endTime = endTime; 2773258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 2783258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 2793258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu @Override 2803258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public void setCallIsAdditional(boolean isAdditional) { 2813258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu Log.d(TAG, "setting isAdditional for call " + callId + " to " + isAdditional); 2823258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.isAdditionalCall = isAdditional; 2833258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 2843258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 2853258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu @Override 2863258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public void setCallIsInterrupted(boolean isInterrupted) { 2873258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu Log.d(TAG, "setting isInterrupted for call " + callId + " to " + isInterrupted); 2883258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.isInterrupted = isInterrupted; 2893258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 2903258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 2913258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu @Override 2923258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public void addCallTechnology(int callTechnology) { 2933258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu Log.d(TAG, "adding callTechnology for call " + callId + ": " + callTechnology); 2943258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.callTechnologies |= callTechnology; 2953258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 2963258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 2973258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu @Override 2983258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public void setCallDisconnectCause(DisconnectCause disconnectCause) { 2993258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu Log.d(TAG, "setting disconnectCause for call " + callId + " to " + disconnectCause); 3003258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.callTerminationReason = disconnectCause; 3013258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 3023258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 3033258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu @Override 3043258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public void setCreatedFromExistingConnection(boolean createdFromExistingConnection) { 3053258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu Log.d(TAG, "setting createdFromExistingConnection for call " + callId + " to " 3063258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu + createdFromExistingConnection); 3073258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.createdFromExistingConnection = createdFromExistingConnection; 3083258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 3093258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 3103258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu @Override 3113258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public void setCallConnectionService(String connectionServiceName) { 3123258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu Log.d(TAG, "setting connection service for call " + callId + ": " 3133258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu + connectionServiceName); 3143258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu this.connectionService = connectionServiceName; 3153258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 3163258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 3173258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu @Override 318a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger public void setCallEvents(EventManager.EventRecord records) { 319874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu this.callEvents = records; 320874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu } 321874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu 322874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu @Override 3234640c4fc55ca4118351330d68684ca9989661ccdHall Liu public void setCallIsVideo(boolean isVideo) { 3244640c4fc55ca4118351330d68684ca9989661ccdHall Liu this.isVideo = isVideo; 3254640c4fc55ca4118351330d68684ca9989661ccdHall Liu } 3264640c4fc55ca4118351330d68684ca9989661ccdHall Liu 3274640c4fc55ca4118351330d68684ca9989661ccdHall Liu @Override 3284640c4fc55ca4118351330d68684ca9989661ccdHall Liu public void addVideoEvent(int eventId, int videoState) { 3294640c4fc55ca4118351330d68684ca9989661ccdHall Liu long timeSinceLastEvent; 3304640c4fc55ca4118351330d68684ca9989661ccdHall Liu long currentTime = System.currentTimeMillis(); 3314640c4fc55ca4118351330d68684ca9989661ccdHall Liu if (mTimeOfLastVideoEvent < 0) { 3324640c4fc55ca4118351330d68684ca9989661ccdHall Liu timeSinceLastEvent = -1; 3334640c4fc55ca4118351330d68684ca9989661ccdHall Liu } else { 3344640c4fc55ca4118351330d68684ca9989661ccdHall Liu timeSinceLastEvent = roundToOneSigFig(currentTime - mTimeOfLastVideoEvent); 3354640c4fc55ca4118351330d68684ca9989661ccdHall Liu } 3364640c4fc55ca4118351330d68684ca9989661ccdHall Liu mTimeOfLastVideoEvent = currentTime; 3374640c4fc55ca4118351330d68684ca9989661ccdHall Liu 3382f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu videoEvents.add(new TelecomLogClass.VideoEvent() 3392f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .setEventName(eventId) 3402f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .setTimeSinceLastEventMillis(timeSinceLastEvent) 3412f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .setVideoState(videoState)); 3424640c4fc55ca4118351330d68684ca9989661ccdHall Liu } 3434640c4fc55ca4118351330d68684ca9989661ccdHall Liu 3444640c4fc55ca4118351330d68684ca9989661ccdHall Liu @Override 3459d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu public void addInCallService(String serviceName, int type) { 3469d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu inCallServiceInfos.add(new TelecomLogClass.InCallServiceInfo() 3479d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu .setInCallServiceName(serviceName) 3489d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu .setInCallServiceType(type)); 3499d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu } 3509d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu 3519d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu @Override 352d7fe686253f2135a948cafc776aa25db645ec27eHall Liu public void addCallProperties(int properties) { 353d7fe686253f2135a948cafc776aa25db645ec27eHall Liu this.callProperties |= properties; 354d7fe686253f2135a948cafc776aa25db645ec27eHall Liu } 355d7fe686253f2135a948cafc776aa25db645ec27eHall Liu 356d7fe686253f2135a948cafc776aa25db645ec27eHall Liu @Override 3573258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public String toString() { 3583258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu return "{\n" 3593258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu + " startTime: " + startTime + '\n' 3603258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu + " endTime: " + endTime + '\n' 3613258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu + " direction: " + getCallDirectionString() + '\n' 3623258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu + " isAdditionalCall: " + isAdditionalCall + '\n' 3633258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu + " isInterrupted: " + isInterrupted + '\n' 3643258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu + " callTechnologies: " + getCallTechnologiesAsString() + '\n' 3653258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu + " callTerminationReason: " + getCallDisconnectReasonString() + '\n' 366ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu + " connectionService: " + connectionService + '\n' 3674640c4fc55ca4118351330d68684ca9989661ccdHall Liu + " isVideoCall: " + isVideo + '\n' 3689d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu + " inCallServices: " + getInCallServicesString() + '\n' 369d7fe686253f2135a948cafc776aa25db645ec27eHall Liu + " callProperties: " + Connection.propertiesToStringShort(callProperties) 370d7fe686253f2135a948cafc776aa25db645ec27eHall Liu + '\n' 3713258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu + "}\n"; 3723258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 3733258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 374ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu public ParcelableCallAnalytics toParcelableAnalytics() { 3752f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu TelecomLogClass.CallLog analyticsProto = toProto(); 3762f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu List<ParcelableCallAnalytics.AnalyticsEvent> events = 3772f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu Arrays.stream(analyticsProto.callEvents) 3782f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .map(callEventProto -> new ParcelableCallAnalytics.AnalyticsEvent( 3792f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu callEventProto.getEventName(), 3802f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu callEventProto.getTimeSinceLastEventMillis()) 3812f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu ).collect(Collectors.toList()); 3822f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu 3832f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu List<ParcelableCallAnalytics.EventTiming> timings = 3842f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu Arrays.stream(analyticsProto.callTimings) 3852f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .map(callTimingProto -> new ParcelableCallAnalytics.EventTiming( 3862f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu callTimingProto.getTimingName(), 3872f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu callTimingProto.getTimeMillis()) 3882f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu ).collect(Collectors.toList()); 3892f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu 3902f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu ParcelableCallAnalytics result = new ParcelableCallAnalytics( 3912f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu // rounds down to nearest 5 minute mark 3922f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu analyticsProto.getStartTime5Min(), 3932f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu analyticsProto.getCallDurationMillis(), 3942f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu analyticsProto.getType(), 3952f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu analyticsProto.getIsAdditionalCall(), 3962f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu analyticsProto.getIsInterrupted(), 3972f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu analyticsProto.getCallTechnologies(), 3982f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu analyticsProto.getCallTerminationCode(), 3992f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu analyticsProto.getIsEmergencyCall(), 4002f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu analyticsProto.connectionService[0], 4012f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu analyticsProto.getIsCreatedFromExistingConnection(), 4022f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu events, 4032f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu timings); 4042f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu 4052f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu result.setIsVideoCall(analyticsProto.getIsVideoCall()); 4062f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu result.setVideoEvents(Arrays.stream(analyticsProto.videoEvents) 4072f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .map(videoEventProto -> new ParcelableCallAnalytics.VideoEvent( 4082f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu videoEventProto.getEventName(), 4092f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu videoEventProto.getTimeSinceLastEventMillis(), 4102f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu videoEventProto.getVideoState()) 4112f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu ).collect(Collectors.toList())); 4122f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu 4132f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu return result; 4142f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu } 4152f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu 4162f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu public TelecomLogClass.CallLog toProto() { 4172f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu TelecomLogClass.CallLog result = new TelecomLogClass.CallLog(); 4182f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu result.setStartTime5Min( 4192f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu startTime - startTime % ParcelableCallAnalytics.MILLIS_IN_5_MINUTES); 4202f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu 421ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu // Rounds up to the nearest second. 4220bd869ca557dc11950be3e967e7bcc3abf0ca729Hall Liu long callDuration = (endTime == 0 || startTime == 0) ? 0 : endTime - startTime; 423ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu callDuration += (callDuration % MILLIS_IN_1_SECOND == 0) ? 424ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu 0 : (MILLIS_IN_1_SECOND - callDuration % MILLIS_IN_1_SECOND); 4252f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu result.setCallDurationMillis(callDuration); 4262f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu 4272f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu result.setType(callDirection) 4282f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .setIsAdditionalCall(isAdditionalCall) 4292f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .setIsInterrupted(isInterrupted) 4302f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .setCallTechnologies(callTechnologies) 4312f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .setCallTerminationCode( 4322f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu callTerminationReason == null ? 4332f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu ParcelableCallAnalytics.STILL_CONNECTED : 4342f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu callTerminationReason.getCode()) 4352f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .setIsEmergencyCall(isEmergency) 4362f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .setIsCreatedFromExistingConnection(createdFromExistingConnection) 4372f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .setIsEmergencyCall(isEmergency) 438d7fe686253f2135a948cafc776aa25db645ec27eHall Liu .setIsVideoCall(isVideo) 439d7fe686253f2135a948cafc776aa25db645ec27eHall Liu .setConnectionProperties(callProperties); 4402f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu 4412f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu result.connectionService = new String[] {connectionService}; 442874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu if (callEvents != null) { 4432f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu result.callEvents = convertLogEventsToProtoEvents(callEvents.getEvents()); 4442f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu result.callTimings = callEvents.extractEventTimings().stream() 4452f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .map(Analytics::logEventTimingToProtoEventTiming) 4462f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .toArray(TelecomLogClass.EventTimingEntry[]::new); 447874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu } 4482f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu result.videoEvents = 4492f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu videoEvents.toArray(new TelecomLogClass.VideoEvent[videoEvents.size()]); 4509d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu result.inCallServices = inCallServiceInfos.toArray( 4519d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu new TelecomLogClass.InCallServiceInfo[inCallServiceInfos.size()]); 4529d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu 4534640c4fc55ca4118351330d68684ca9989661ccdHall Liu return result; 454ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu } 455ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu 4563258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu private String getCallDirectionString() { 4573258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu switch (callDirection) { 4583258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu case UNKNOWN_DIRECTION: 4593258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu return "UNKNOWN"; 4603258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu case INCOMING_DIRECTION: 4613258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu return "INCOMING"; 4623258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu case OUTGOING_DIRECTION: 4633258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu return "OUTGOING"; 4643258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu default: 4653258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu return "UNKNOWN"; 4663258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 4673258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 4683258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 4693258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu private String getCallTechnologiesAsString() { 4703258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu StringBuilder s = new StringBuilder(); 4713258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu s.append('['); 4723258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu if ((callTechnologies & CDMA_PHONE) != 0) s.append("CDMA "); 4733258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu if ((callTechnologies & GSM_PHONE) != 0) s.append("GSM "); 4743258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu if ((callTechnologies & SIP_PHONE) != 0) s.append("SIP "); 4753258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu if ((callTechnologies & IMS_PHONE) != 0) s.append("IMS "); 4763258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu if ((callTechnologies & THIRD_PARTY_PHONE) != 0) s.append("THIRD_PARTY "); 4773258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu s.append(']'); 4783258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu return s.toString(); 4793258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 4803258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 4813258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu private String getCallDisconnectReasonString() { 4823258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu if (callTerminationReason != null) { 4833258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu return callTerminationReason.toString(); 4843258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } else { 4853258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu return "NOT SET"; 4863258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 4873258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 4889d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu 4899d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu private String getInCallServicesString() { 4909d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu StringBuilder s = new StringBuilder(); 4919d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu s.append("[\n"); 4929d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu for (TelecomLogClass.InCallServiceInfo service : inCallServiceInfos) { 4939d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu s.append(" "); 4949d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu s.append("name: "); 4959d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu s.append(service.getInCallServiceName()); 4969d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu s.append(" type: "); 4979d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu s.append(service.getInCallServiceType()); 4989d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu s.append("\n"); 4999d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu } 5009d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu s.append("]"); 5019d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu return s.toString(); 5029d15ca4316bb3a89bba11b62d2e17e2fb80fdc74Hall Liu } 5033258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 5043258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public static final String TAG = "TelecomAnalytics"; 5053258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 5063258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu // Constants for call direction 507ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu public static final int UNKNOWN_DIRECTION = ParcelableCallAnalytics.CALLTYPE_UNKNOWN; 508ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu public static final int INCOMING_DIRECTION = ParcelableCallAnalytics.CALLTYPE_INCOMING; 509ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu public static final int OUTGOING_DIRECTION = ParcelableCallAnalytics.CALLTYPE_OUTGOING; 5103258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 5113258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu // Constants for call technology 512ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu public static final int CDMA_PHONE = ParcelableCallAnalytics.CDMA_PHONE; 513ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu public static final int GSM_PHONE = ParcelableCallAnalytics.GSM_PHONE; 514ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu public static final int IMS_PHONE = ParcelableCallAnalytics.IMS_PHONE; 515ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu public static final int SIP_PHONE = ParcelableCallAnalytics.SIP_PHONE; 516ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu public static final int THIRD_PARTY_PHONE = ParcelableCallAnalytics.THIRD_PARTY_PHONE; 517ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu 5184640c4fc55ca4118351330d68684ca9989661ccdHall Liu // Constants for video events 5194640c4fc55ca4118351330d68684ca9989661ccdHall Liu public static final int SEND_LOCAL_SESSION_MODIFY_REQUEST = 5204640c4fc55ca4118351330d68684ca9989661ccdHall Liu ParcelableCallAnalytics.VideoEvent.SEND_LOCAL_SESSION_MODIFY_REQUEST; 5214640c4fc55ca4118351330d68684ca9989661ccdHall Liu public static final int SEND_LOCAL_SESSION_MODIFY_RESPONSE = 5224640c4fc55ca4118351330d68684ca9989661ccdHall Liu ParcelableCallAnalytics.VideoEvent.SEND_LOCAL_SESSION_MODIFY_RESPONSE; 5234640c4fc55ca4118351330d68684ca9989661ccdHall Liu public static final int RECEIVE_REMOTE_SESSION_MODIFY_REQUEST = 5244640c4fc55ca4118351330d68684ca9989661ccdHall Liu ParcelableCallAnalytics.VideoEvent.RECEIVE_REMOTE_SESSION_MODIFY_REQUEST; 5254640c4fc55ca4118351330d68684ca9989661ccdHall Liu public static final int RECEIVE_REMOTE_SESSION_MODIFY_RESPONSE = 5264640c4fc55ca4118351330d68684ca9989661ccdHall Liu ParcelableCallAnalytics.VideoEvent.RECEIVE_REMOTE_SESSION_MODIFY_RESPONSE; 5274640c4fc55ca4118351330d68684ca9989661ccdHall Liu 528ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu public static final long MILLIS_IN_1_SECOND = ParcelableCallAnalytics.MILLIS_IN_1_SECOND; 5293258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 530d93b9ececca0fb8a2cc63858ce59012eb6fc17e9Hall Liu public static final int MAX_NUM_CALLS_TO_STORE = 100; 531d93b9ececca0fb8a2cc63858ce59012eb6fc17e9Hall Liu 5323258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu private static final Object sLock = new Object(); // Coarse lock for all of analytics 5333258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu private static final Map<String, CallInfoImpl> sCallIdToInfo = new HashMap<>(); 534d93b9ececca0fb8a2cc63858ce59012eb6fc17e9Hall Liu private static final LinkedList<String> sActiveCallIds = new LinkedList<>(); 535874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu private static final List<SessionTiming> sSessionTimings = new LinkedList<>(); 536874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu 537874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu public static void addSessionTiming(String sessionName, long time) { 538874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu if (sLogSessionToSessionId.containsKey(sessionName)) { 539874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu synchronized (sLock) { 540874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu sSessionTimings.add(new SessionTiming(sLogSessionToSessionId.get(sessionName), 541874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu time)); 542874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu } 543874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu } 544874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu } 5453258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 5463258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public static CallInfo initiateCallAnalytics(String callId, int direction) { 5473258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu Log.d(TAG, "Starting analytics for call " + callId); 5483258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu CallInfoImpl callInfo = new CallInfoImpl(callId, direction); 5493258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu synchronized (sLock) { 550d93b9ececca0fb8a2cc63858ce59012eb6fc17e9Hall Liu while (sActiveCallIds.size() >= MAX_NUM_CALLS_TO_STORE) { 551d93b9ececca0fb8a2cc63858ce59012eb6fc17e9Hall Liu String callToRemove = sActiveCallIds.remove(); 552d93b9ececca0fb8a2cc63858ce59012eb6fc17e9Hall Liu sCallIdToInfo.remove(callToRemove); 553d93b9ececca0fb8a2cc63858ce59012eb6fc17e9Hall Liu } 5543258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu sCallIdToInfo.put(callId, callInfo); 555d93b9ececca0fb8a2cc63858ce59012eb6fc17e9Hall Liu sActiveCallIds.add(callId); 5563258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 5573258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu return callInfo; 5583258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 5593258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 560874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu public static TelecomAnalytics dumpToParcelableAnalytics() { 561874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu List<ParcelableCallAnalytics> calls = new LinkedList<>(); 562874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu List<SessionTiming> sessionTimings = new LinkedList<>(); 563ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu synchronized (sLock) { 564874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu calls.addAll(sCallIdToInfo.values().stream() 565874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu .map(CallInfoImpl::toParcelableAnalytics) 566874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu .collect(Collectors.toList())); 567874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu sessionTimings.addAll(sSessionTimings); 568ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu sCallIdToInfo.clear(); 569874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu sSessionTimings.clear(); 570ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu } 571874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu return new TelecomAnalytics(sessionTimings, calls); 572ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu } 573ecd74a56dbce2d15ff46ad3e64a16dfe8b6c734fHall Liu 5742f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu public static void dumpToEncodedProto(PrintWriter pw, String[] args) { 5752f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu TelecomLogClass.TelecomLog result = new TelecomLogClass.TelecomLog(); 5762f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu 5772f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu synchronized (sLock) { 5782f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu result.callLogs = sCallIdToInfo.values().stream() 5792f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .map(CallInfoImpl::toProto) 5802f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .toArray(TelecomLogClass.CallLog[]::new); 5812f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu result.sessionTimings = sSessionTimings.stream() 5822f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .map(timing -> new TelecomLogClass.LogSessionTiming() 5832f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .setSessionEntryPoint(timing.getKey()) 5842f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .setTimeMillis(timing.getTime())) 5852f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .toArray(TelecomLogClass.LogSessionTiming[]::new); 5862f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu if (args.length > 1 && CLEAR_ANALYTICS_ARG.equals(args[1])) { 5872f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu sCallIdToInfo.clear(); 5882f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu sSessionTimings.clear(); 5892f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu } 5902f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu } 5912f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu String encodedProto = Base64.encodeToString( 5922f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu TelecomLogClass.TelecomLog.toByteArray(result), Base64.DEFAULT); 5932f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu pw.write(encodedProto); 5942f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu } 5952f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu 5963258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public static void dump(IndentingPrintWriter writer) { 5973258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu synchronized (sLock) { 598874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu int prefixLength = CallsManager.TELECOM_CALL_ID_PREFIX.length(); 599874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu List<String> callIds = new ArrayList<>(sCallIdToInfo.keySet()); 600874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu // Sort the analytics in increasing order of call IDs 601d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu try { 602d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu Collections.sort(callIds, (id1, id2) -> { 603d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu int i1, i2; 604d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu try { 605d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu i1 = Integer.valueOf(id1.substring(prefixLength)); 606d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu } catch (NumberFormatException e) { 607d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu i1 = Integer.MAX_VALUE; 608d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu } 609d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu 610d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu try { 611d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu i2 = Integer.valueOf(id2.substring(prefixLength)); 612d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu } catch (NumberFormatException e) { 613d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu i2 = Integer.MAX_VALUE; 614d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu } 615d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu return i1 - i2; 616d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu }); 617d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu } catch (IllegalArgumentException e) { 618d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu // do nothing, leave the list in a partially sorted state. 619d7e370d9a0b5fa4b99e8a832ba0b690f0f8fb4beHall Liu } 620874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu 621874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu for (String callId : callIds) { 622874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu writer.printf("Call %s: ", callId); 623874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu writer.println(sCallIdToInfo.get(callId).toString()); 6243258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 625874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu 626874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu Map<Integer, Double> averageTimings = SessionTiming.averageTimings(sSessionTimings); 627874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu averageTimings.entrySet().stream() 628874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu .filter(e -> sSessionIdToLogSession.containsKey(e.getKey())) 629874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu .forEach(e -> writer.printf("%s: %.2f\n", 630874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu sSessionIdToLogSession.get(e.getKey()), e.getValue())); 6313258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 6323258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 6333258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 6343258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public static void reset() { 6353258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu synchronized (sLock) { 6363258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu sCallIdToInfo.clear(); 6373258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 6383258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 6393258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu 6403258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu /** 641874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu * Returns a copy of callIdToInfo. Use only for testing. 6423258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu */ 643874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu @VisibleForTesting 6443258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu public static Map<String, CallInfoImpl> cloneData() { 6453258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu synchronized (sLock) { 6463258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu Map<String, CallInfoImpl> result = new HashMap<>(sCallIdToInfo.size()); 6473258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu for (Map.Entry<String, CallInfoImpl> entry : sCallIdToInfo.entrySet()) { 6483258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu result.put(entry.getKey(), new CallInfoImpl(entry.getValue())); 6493258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 6503258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu return result; 6513258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 6523258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu } 653874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu 6542f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu private static TelecomLogClass.Event[] convertLogEventsToProtoEvents( 655a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger List<EventManager.Event> logEvents) { 656874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu long timeOfLastEvent = -1; 6572f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu ArrayList<TelecomLogClass.Event> events = new ArrayList<>(logEvents.size()); 658a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger for (EventManager.Event logEvent : logEvents) { 659874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu if (sLogEventToAnalyticsEvent.containsKey(logEvent.eventId)) { 6602f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu TelecomLogClass.Event event = new TelecomLogClass.Event(); 6612f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu event.setEventName(sLogEventToAnalyticsEvent.get(logEvent.eventId)); 6622f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu event.setTimeSinceLastEventMillis(roundToOneSigFig( 6632f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu timeOfLastEvent < 0 ? -1 : logEvent.time - timeOfLastEvent)); 6642f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu events.add(event); 665874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu timeOfLastEvent = logEvent.time; 666874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu } 667874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu } 6682f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu return events.toArray(new TelecomLogClass.Event[events.size()]); 669874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu } 670874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu 6712f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu private static TelecomLogClass.EventTimingEntry logEventTimingToProtoEventTiming( 672a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebinger EventManager.EventRecord.EventTiming logEventTiming) { 673874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu int analyticsEventTimingName = 674874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu sLogEventTimingToAnalyticsEventTiming.containsKey(logEventTiming.name) ? 675874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu sLogEventTimingToAnalyticsEventTiming.get(logEventTiming.name) : 676874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu ParcelableCallAnalytics.EventTiming.INVALID; 6772f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu return new TelecomLogClass.EventTimingEntry() 6782f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .setTimingName(analyticsEventTimingName) 6792f4f0a038dbf9f6372ac8c9b1535f8cc8d0f8256Hall Liu .setTimeMillis(logEventTiming.time); 680874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu } 681874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu 682874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu @VisibleForTesting 683874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu public static long roundToOneSigFig(long val) { 684874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu if (val == 0) { 685874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu return val; 686874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu } 687874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu int logVal = (int) Math.floor(Math.log10(val < 0 ? -val : val)); 688874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu double s = Math.pow(10, logVal); 689874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu double dec = val / s; 690874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu return (long) (Math.round(dec) * s); 691874c0f8fa95a5da5a82e67c1fe39697883d753ebHall Liu } 6923258720f5526f766aa26c19cf01b32ac20d19d1dHall Liu} 693