1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony.metrics; 18 19 import static android.text.format.DateUtils.MINUTE_IN_MILLIS; 20 21 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ANSWER; 22 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_CDMA_SEND_SMS; 23 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_DEACTIVATE_DATA_CALL; 24 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_DIAL; 25 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_HANGUP; 26 import static com.android.internal.telephony.RILConstants 27 .RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND; 28 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND; 29 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IMS_SEND_SMS; 30 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SEND_SMS; 31 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SEND_SMS_EXPECT_MORE; 32 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SETUP_DATA_CALL; 33 import static com.android.internal.telephony.nano.TelephonyProto.PdpType.PDP_TYPE_IP; 34 import static com.android.internal.telephony.nano.TelephonyProto.PdpType.PDP_TYPE_IPV4V6; 35 import static com.android.internal.telephony.nano.TelephonyProto.PdpType.PDP_TYPE_IPV6; 36 import static com.android.internal.telephony.nano.TelephonyProto.PdpType.PDP_TYPE_PPP; 37 import static com.android.internal.telephony.nano.TelephonyProto.PdpType.PDP_UNKNOWN; 38 39 import android.os.Build; 40 import android.os.SystemClock; 41 import android.telephony.Rlog; 42 import android.telephony.ServiceState; 43 import android.telephony.TelephonyHistogram; 44 import android.text.TextUtils; 45 import android.util.Base64; 46 import android.util.SparseArray; 47 48 import com.android.ims.ImsConfig; 49 import com.android.ims.ImsReasonInfo; 50 import com.android.ims.internal.ImsCallSession; 51 import com.android.internal.telephony.GsmCdmaConnection; 52 import com.android.internal.telephony.PhoneConstants; 53 import com.android.internal.telephony.RIL; 54 import com.android.internal.telephony.RILConstants; 55 import com.android.internal.telephony.SmsResponse; 56 import com.android.internal.telephony.UUSInfo; 57 import com.android.internal.telephony.dataconnection.DataCallResponse; 58 import com.android.internal.telephony.imsphone.ImsPhoneCall; 59 import com.android.internal.telephony.nano.TelephonyProto; 60 import com.android.internal.telephony.nano.TelephonyProto.ImsCapabilities; 61 import com.android.internal.telephony.nano.TelephonyProto.ImsConnectionState; 62 import com.android.internal.telephony.nano.TelephonyProto.RilDataCall; 63 import com.android.internal.telephony.nano.TelephonyProto.SmsSession; 64 import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession; 65 import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession.Event.CallState; 66 import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession.Event.RilCall; 67 import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession.Event.RilCall.Type; 68 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent; 69 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.ModemRestart; 70 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilDeactivateDataCall; 71 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilSetupDataCall; 72 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilSetupDataCallResponse; 73 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilSetupDataCallResponse 74 .RilDataCallFailCause; 75 import com.android.internal.telephony.nano.TelephonyProto.TelephonyLog; 76 import com.android.internal.telephony.nano.TelephonyProto.TelephonyServiceState; 77 import com.android.internal.telephony.nano.TelephonyProto.TelephonySettings; 78 import com.android.internal.telephony.nano.TelephonyProto.TimeInterval; 79 import com.android.internal.util.IndentingPrintWriter; 80 81 import java.io.FileDescriptor; 82 import java.io.PrintWriter; 83 import java.util.ArrayDeque; 84 import java.util.ArrayList; 85 import java.util.Arrays; 86 import java.util.Deque; 87 import java.util.List; 88 89 /** 90 * Telephony metrics holds all metrics events and convert it into telephony proto buf. 91 * @hide 92 */ 93 public class TelephonyMetrics { 94 95 private static final String TAG = TelephonyMetrics.class.getSimpleName(); 96 97 private static final boolean DBG = true; 98 private static final boolean VDBG = false; // STOPSHIP if true 99 100 /** Maximum telephony events stored */ 101 private static final int MAX_TELEPHONY_EVENTS = 1000; 102 103 /** Maximum call sessions stored */ 104 private static final int MAX_COMPLETED_CALL_SESSIONS = 50; 105 106 /** Maximum sms sessions stored */ 107 private static final int MAX_COMPLETED_SMS_SESSIONS = 500; 108 109 /** For reducing the timing precision for privacy purposes */ 110 private static final int SESSION_START_PRECISION_MINUTES = 5; 111 112 /** The TelephonyMetrics singleton instance */ 113 private static TelephonyMetrics sInstance; 114 115 /** Telephony events */ 116 private final Deque<TelephonyEvent> mTelephonyEvents = new ArrayDeque<>(); 117 118 /** 119 * In progress call sessions. Note that each phone can only have up to 1 in progress call 120 * session (might contains multiple calls). Having a sparse array in case we need to support 121 * DSDA in the future. 122 */ 123 private final SparseArray<InProgressCallSession> mInProgressCallSessions = new SparseArray<>(); 124 125 /** The completed call sessions */ 126 private final Deque<TelephonyCallSession> mCompletedCallSessions = new ArrayDeque<>(); 127 128 /** The in-progress SMS sessions. When finished, it will be moved into the completed sessions */ 129 private final SparseArray<InProgressSmsSession> mInProgressSmsSessions = new SparseArray<>(); 130 131 /** The completed SMS sessions */ 132 private final Deque<SmsSession> mCompletedSmsSessions = new ArrayDeque<>(); 133 134 /** Last service state. This is for injecting the base of a new log or a new call/sms session */ 135 private final SparseArray<TelephonyServiceState> mLastServiceState = new SparseArray<>(); 136 137 /** 138 * Last ims capabilities. This is for injecting the base of a new log or a new call/sms 139 * session 140 */ 141 private final SparseArray<ImsCapabilities> mLastImsCapabilities = new SparseArray<>(); 142 143 /** 144 * Last IMS connection state. This is for injecting the base of a new log or a new call/sms 145 * session 146 */ 147 private final SparseArray<ImsConnectionState> mLastImsConnectionState = new SparseArray<>(); 148 149 /** 150 * Last settings state. This is for deduping same settings event logged. 151 */ 152 private final SparseArray<TelephonySettings> mLastSettings = new SparseArray<>(); 153 154 /** The start system time of the TelephonyLog in milliseconds*/ 155 private long mStartSystemTimeMs; 156 157 /** The start elapsed time of the TelephonyLog in milliseconds*/ 158 private long mStartElapsedTimeMs; 159 160 /** Indicating if some of the telephony events are dropped in this log */ 161 private boolean mTelephonyEventsDropped = false; 162 TelephonyMetrics()163 public TelephonyMetrics() { 164 reset(); 165 } 166 167 /** 168 * Get the singleton instance of telephony metrics. 169 * 170 * @return The instance 171 */ getInstance()172 public synchronized static TelephonyMetrics getInstance() { 173 if (sInstance == null) { 174 sInstance = new TelephonyMetrics(); 175 } 176 177 return sInstance; 178 } 179 180 /** 181 * Dump the state of various objects, add calls to other objects as desired. 182 * 183 * @param fd File descriptor 184 * @param pw Print writer 185 * @param args Arguments 186 */ dump(FileDescriptor fd, PrintWriter pw, String[] args)187 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 188 if (args != null && args.length > 0) { 189 switch (args[0]) { 190 case "--metrics": 191 printAllMetrics(pw); 192 break; 193 case "--metricsproto": 194 pw.println(convertProtoToBase64String(buildProto())); 195 reset(); 196 break; 197 } 198 } 199 } 200 201 /** 202 * Convert the telephony event to string 203 * 204 * @param event The event in integer 205 * @return The event in string 206 */ telephonyEventToString(int event)207 private static String telephonyEventToString(int event) { 208 switch (event) { 209 case TelephonyEvent.Type.UNKNOWN: 210 return "UNKNOWN"; 211 case TelephonyEvent.Type.SETTINGS_CHANGED: 212 return "SETTINGS_CHANGED"; 213 case TelephonyEvent.Type.RIL_SERVICE_STATE_CHANGED: 214 return "RIL_SERVICE_STATE_CHANGED"; 215 case TelephonyEvent.Type.IMS_CONNECTION_STATE_CHANGED: 216 return "IMS_CONNECTION_STATE_CHANGED"; 217 case TelephonyEvent.Type.IMS_CAPABILITIES_CHANGED: 218 return "IMS_CAPABILITIES_CHANGED"; 219 case TelephonyEvent.Type.DATA_CALL_SETUP: 220 return "DATA_CALL_SETUP"; 221 case TelephonyEvent.Type.DATA_CALL_SETUP_RESPONSE: 222 return "DATA_CALL_SETUP_RESPONSE"; 223 case TelephonyEvent.Type.DATA_CALL_LIST_CHANGED: 224 return "DATA_CALL_LIST_CHANGED"; 225 case TelephonyEvent.Type.DATA_CALL_DEACTIVATE: 226 return "DATA_CALL_DEACTIVATE"; 227 case TelephonyEvent.Type.DATA_CALL_DEACTIVATE_RESPONSE: 228 return "DATA_CALL_DEACTIVATE_RESPONSE"; 229 case TelephonyEvent.Type.DATA_STALL_ACTION: 230 return "DATA_STALL_ACTION"; 231 case TelephonyEvent.Type.MODEM_RESTART: 232 return "MODEM_RESTART"; 233 default: 234 return Integer.toString(event); 235 } 236 } 237 238 /** 239 * Convert the call session event into string 240 * 241 * @param event The event in integer 242 * @return The event in String 243 */ callSessionEventToString(int event)244 private static String callSessionEventToString(int event) { 245 switch (event) { 246 case TelephonyCallSession.Event.Type.EVENT_UNKNOWN: 247 return "EVENT_UNKNOWN"; 248 case TelephonyCallSession.Event.Type.SETTINGS_CHANGED: 249 return "SETTINGS_CHANGED"; 250 case TelephonyCallSession.Event.Type.RIL_SERVICE_STATE_CHANGED: 251 return "RIL_SERVICE_STATE_CHANGED"; 252 case TelephonyCallSession.Event.Type.IMS_CONNECTION_STATE_CHANGED: 253 return "IMS_CONNECTION_STATE_CHANGED"; 254 case TelephonyCallSession.Event.Type.IMS_CAPABILITIES_CHANGED: 255 return "IMS_CAPABILITIES_CHANGED"; 256 case TelephonyCallSession.Event.Type.DATA_CALL_LIST_CHANGED: 257 return "DATA_CALL_LIST_CHANGED"; 258 case TelephonyCallSession.Event.Type.RIL_REQUEST: 259 return "RIL_REQUEST"; 260 case TelephonyCallSession.Event.Type.RIL_RESPONSE: 261 return "RIL_RESPONSE"; 262 case TelephonyCallSession.Event.Type.RIL_CALL_RING: 263 return "RIL_CALL_RING"; 264 case TelephonyCallSession.Event.Type.RIL_CALL_SRVCC: 265 return "RIL_CALL_SRVCC"; 266 case TelephonyCallSession.Event.Type.RIL_CALL_LIST_CHANGED: 267 return "RIL_CALL_LIST_CHANGED"; 268 case TelephonyCallSession.Event.Type.IMS_COMMAND: 269 return "IMS_COMMAND"; 270 case TelephonyCallSession.Event.Type.IMS_COMMAND_RECEIVED: 271 return "IMS_COMMAND_RECEIVED"; 272 case TelephonyCallSession.Event.Type.IMS_COMMAND_FAILED: 273 return "IMS_COMMAND_FAILED"; 274 case TelephonyCallSession.Event.Type.IMS_COMMAND_COMPLETE: 275 return "IMS_COMMAND_COMPLETE"; 276 case TelephonyCallSession.Event.Type.IMS_CALL_RECEIVE: 277 return "IMS_CALL_RECEIVE"; 278 case TelephonyCallSession.Event.Type.IMS_CALL_STATE_CHANGED: 279 return "IMS_CALL_STATE_CHANGED"; 280 case TelephonyCallSession.Event.Type.IMS_CALL_TERMINATED: 281 return "IMS_CALL_TERMINATED"; 282 case TelephonyCallSession.Event.Type.IMS_CALL_HANDOVER: 283 return "IMS_CALL_HANDOVER"; 284 case TelephonyCallSession.Event.Type.IMS_CALL_HANDOVER_FAILED: 285 return "IMS_CALL_HANDOVER_FAILED"; 286 case TelephonyCallSession.Event.Type.PHONE_STATE_CHANGED: 287 return "PHONE_STATE_CHANGED"; 288 case TelephonyCallSession.Event.Type.NITZ_TIME: 289 return "NITZ_TIME"; 290 default: 291 return Integer.toString(event); 292 } 293 } 294 295 /** 296 * Convert the SMS session event into string 297 * @param event The event in integer 298 * @return The event in String 299 */ smsSessionEventToString(int event)300 private static String smsSessionEventToString(int event) { 301 switch (event) { 302 case SmsSession.Event.Type.EVENT_UNKNOWN: 303 return "EVENT_UNKNOWN"; 304 case SmsSession.Event.Type.SETTINGS_CHANGED: 305 return "SETTINGS_CHANGED"; 306 case SmsSession.Event.Type.RIL_SERVICE_STATE_CHANGED: 307 return "RIL_SERVICE_STATE_CHANGED"; 308 case SmsSession.Event.Type.IMS_CONNECTION_STATE_CHANGED: 309 return "IMS_CONNECTION_STATE_CHANGED"; 310 case SmsSession.Event.Type.IMS_CAPABILITIES_CHANGED: 311 return "IMS_CAPABILITIES_CHANGED"; 312 case SmsSession.Event.Type.DATA_CALL_LIST_CHANGED: 313 return "DATA_CALL_LIST_CHANGED"; 314 case SmsSession.Event.Type.SMS_SEND: 315 return "SMS_SEND"; 316 case SmsSession.Event.Type.SMS_SEND_RESULT: 317 return "SMS_SEND_RESULT"; 318 case SmsSession.Event.Type.SMS_RECEIVED: 319 return "SMS_RECEIVED"; 320 default: 321 return Integer.toString(event); 322 } 323 } 324 325 /** 326 * Print all metrics data for debugging purposes 327 * 328 * @param rawWriter Print writer 329 */ printAllMetrics(PrintWriter rawWriter)330 private synchronized void printAllMetrics(PrintWriter rawWriter) { 331 final IndentingPrintWriter pw = new IndentingPrintWriter(rawWriter, " "); 332 333 pw.println("Telephony metrics proto:"); 334 pw.println("------------------------------------------"); 335 pw.println("Telephony events:"); 336 pw.increaseIndent(); 337 for (TelephonyEvent event : mTelephonyEvents) { 338 pw.print(event.timestampMillis); 339 pw.print(" ["); 340 pw.print(event.phoneId); 341 pw.print("] "); 342 343 pw.print("T="); 344 if (event.type == TelephonyEvent.Type.RIL_SERVICE_STATE_CHANGED) { 345 pw.print(telephonyEventToString(event.type) 346 + "(" + event.serviceState.dataRat + ")"); 347 } else { 348 pw.print(telephonyEventToString(event.type)); 349 } 350 351 pw.println(""); 352 } 353 354 pw.decreaseIndent(); 355 pw.println("Call sessions:"); 356 pw.increaseIndent(); 357 358 for (TelephonyCallSession callSession : mCompletedCallSessions) { 359 pw.println("Start time in minutes: " + callSession.startTimeMinutes); 360 pw.println("Events dropped: " + callSession.eventsDropped); 361 362 pw.println("Events: "); 363 pw.increaseIndent(); 364 for (TelephonyCallSession.Event event : callSession.events) { 365 pw.print(event.delay); 366 pw.print(" T="); 367 if (event.type == TelephonyCallSession.Event.Type.RIL_SERVICE_STATE_CHANGED) { 368 pw.println(callSessionEventToString(event.type) 369 + "(" + event.serviceState.dataRat + ")"); 370 } else if (event.type == TelephonyCallSession.Event.Type.RIL_CALL_LIST_CHANGED) { 371 pw.println(callSessionEventToString(event.type)); 372 pw.increaseIndent(); 373 for (RilCall call : event.calls) { 374 pw.println(call.index + ". Type = " + call.type + " State = " 375 + call.state + " End Reason " + call.callEndReason 376 + " isMultiparty = " + call.isMultiparty); 377 } 378 pw.decreaseIndent(); 379 } else { 380 pw.println(callSessionEventToString(event.type)); 381 } 382 } 383 pw.decreaseIndent(); 384 } 385 386 pw.decreaseIndent(); 387 pw.println("Sms sessions:"); 388 pw.increaseIndent(); 389 390 int count = 0; 391 for (SmsSession smsSession : mCompletedSmsSessions) { 392 count++; 393 pw.print("[" + count + "] Start time in minutes: " 394 + smsSession.startTimeMinutes); 395 396 if (smsSession.eventsDropped) { 397 pw.println(", events dropped: " + smsSession.eventsDropped); 398 } 399 pw.println("Events: "); 400 pw.increaseIndent(); 401 for (SmsSession.Event event : smsSession.events) { 402 pw.print(event.delay); 403 pw.print(" T="); 404 pw.println(smsSessionEventToString(event.type)); 405 } 406 pw.decreaseIndent(); 407 } 408 409 pw.decreaseIndent(); 410 } 411 412 /** 413 * Convert the telephony proto into Base-64 encoded string 414 * 415 * @param proto Telephony proto 416 * @return Encoded string 417 */ convertProtoToBase64String(TelephonyLog proto)418 private static String convertProtoToBase64String(TelephonyLog proto) { 419 return Base64.encodeToString( 420 TelephonyProto.TelephonyLog.toByteArray(proto), Base64.DEFAULT); 421 } 422 423 /** 424 * Reset all events and sessions 425 */ reset()426 private synchronized void reset() { 427 mTelephonyEvents.clear(); 428 mCompletedCallSessions.clear(); 429 mCompletedSmsSessions.clear(); 430 431 mTelephonyEventsDropped = false; 432 433 mStartSystemTimeMs = System.currentTimeMillis(); 434 mStartElapsedTimeMs = SystemClock.elapsedRealtime(); 435 436 // Insert the last known service state, ims capabilities, and ims connection states as the 437 // base. 438 for (int i = 0; i < mLastServiceState.size(); i++) { 439 final int key = mLastServiceState.keyAt(i); 440 441 TelephonyEvent event = new TelephonyEventBuilder(mStartElapsedTimeMs, key) 442 .setServiceState(mLastServiceState.get(key)).build(); 443 addTelephonyEvent(event); 444 } 445 446 for (int i = 0; i < mLastImsCapabilities.size(); i++) { 447 final int key = mLastImsCapabilities.keyAt(i); 448 449 TelephonyEvent event = new TelephonyEventBuilder(mStartElapsedTimeMs, key) 450 .setImsCapabilities(mLastImsCapabilities.get(key)).build(); 451 addTelephonyEvent(event); 452 } 453 454 for (int i = 0; i < mLastImsConnectionState.size(); i++) { 455 final int key = mLastImsConnectionState.keyAt(i); 456 457 TelephonyEvent event = new TelephonyEventBuilder(mStartElapsedTimeMs, key) 458 .setImsConnectionState(mLastImsConnectionState.get(key)).build(); 459 addTelephonyEvent(event); 460 } 461 } 462 463 /** 464 * Build the telephony proto 465 * 466 * @return Telephony proto 467 */ buildProto()468 private synchronized TelephonyLog buildProto() { 469 470 TelephonyLog log = new TelephonyLog(); 471 // Build telephony events 472 log.events = new TelephonyEvent[mTelephonyEvents.size()]; 473 mTelephonyEvents.toArray(log.events); 474 log.eventsDropped = mTelephonyEventsDropped; 475 476 // Build call sessions 477 log.callSessions = new TelephonyCallSession[mCompletedCallSessions.size()]; 478 mCompletedCallSessions.toArray(log.callSessions); 479 480 // Build SMS sessions 481 log.smsSessions = new SmsSession[mCompletedSmsSessions.size()]; 482 mCompletedSmsSessions.toArray(log.smsSessions); 483 484 // Build histogram. Currently we only support RIL histograms. 485 List<TelephonyHistogram> rilHistograms = RIL.getTelephonyRILTimingHistograms(); 486 log.histograms = new TelephonyProto.TelephonyHistogram[rilHistograms.size()]; 487 for (int i = 0; i < rilHistograms.size(); i++) { 488 log.histograms[i] = new TelephonyProto.TelephonyHistogram(); 489 TelephonyHistogram rilHistogram = rilHistograms.get(i); 490 TelephonyProto.TelephonyHistogram histogramProto = log.histograms[i]; 491 492 histogramProto.category = rilHistogram.getCategory(); 493 histogramProto.id = rilHistogram.getId(); 494 histogramProto.minTimeMillis = rilHistogram.getMinTime(); 495 histogramProto.maxTimeMillis = rilHistogram.getMaxTime(); 496 histogramProto.avgTimeMillis = rilHistogram.getAverageTime(); 497 histogramProto.count = rilHistogram.getSampleCount(); 498 histogramProto.bucketCount = rilHistogram.getBucketCount(); 499 histogramProto.bucketEndPoints = rilHistogram.getBucketEndPoints(); 500 histogramProto.bucketCounters = rilHistogram.getBucketCounters(); 501 } 502 503 // Log the starting system time 504 log.startTime = new TelephonyProto.Time(); 505 log.startTime.systemTimestampMillis = mStartSystemTimeMs; 506 log.startTime.elapsedTimestampMillis = mStartElapsedTimeMs; 507 508 log.endTime = new TelephonyProto.Time(); 509 log.endTime.systemTimestampMillis = System.currentTimeMillis(); 510 log.endTime.elapsedTimestampMillis = SystemClock.elapsedRealtime(); 511 512 return log; 513 } 514 515 /** 516 * Reduce precision to meet privacy requirements. 517 * 518 * @param timestamp timestamp in milliseconds 519 * @return Precision reduced timestamp in minutes 520 */ roundSessionStart(long timestamp)521 static int roundSessionStart(long timestamp) { 522 return (int) ((timestamp) / (MINUTE_IN_MILLIS * SESSION_START_PRECISION_MINUTES) 523 * (SESSION_START_PRECISION_MINUTES)); 524 } 525 526 /** 527 * Get the time interval with reduced prevision 528 * 529 * @param previousTimestamp Previous timestamp in milliseconds 530 * @param currentTimestamp Current timestamp in milliseconds 531 * @return The time interval 532 */ toPrivacyFuzzedTimeInterval(long previousTimestamp, long currentTimestamp)533 static int toPrivacyFuzzedTimeInterval(long previousTimestamp, long currentTimestamp) { 534 long diff = currentTimestamp - previousTimestamp; 535 if (diff < 0) { 536 return TimeInterval.TI_UNKNOWN; 537 } else if (diff <= 10) { 538 return TimeInterval.TI_10_MILLIS; 539 } else if (diff <= 20) { 540 return TimeInterval.TI_20_MILLIS; 541 } else if (diff <= 50) { 542 return TimeInterval.TI_50_MILLIS; 543 } else if (diff <= 100) { 544 return TimeInterval.TI_100_MILLIS; 545 } else if (diff <= 200) { 546 return TimeInterval.TI_200_MILLIS; 547 } else if (diff <= 500) { 548 return TimeInterval.TI_500_MILLIS; 549 } else if (diff <= 1000) { 550 return TimeInterval.TI_1_SEC; 551 } else if (diff <= 2000) { 552 return TimeInterval.TI_2_SEC; 553 } else if (diff <= 5000) { 554 return TimeInterval.TI_5_SEC; 555 } else if (diff <= 10000) { 556 return TimeInterval.TI_10_SEC; 557 } else if (diff <= 30000) { 558 return TimeInterval.TI_30_SEC; 559 } else if (diff <= 60000) { 560 return TimeInterval.TI_1_MINUTE; 561 } else if (diff <= 180000) { 562 return TimeInterval.TI_3_MINUTES; 563 } else if (diff <= 600000) { 564 return TimeInterval.TI_10_MINUTES; 565 } else if (diff <= 1800000) { 566 return TimeInterval.TI_30_MINUTES; 567 } else if (diff <= 3600000) { 568 return TimeInterval.TI_1_HOUR; 569 } else if (diff <= 7200000) { 570 return TimeInterval.TI_2_HOURS; 571 } else if (diff <= 14400000) { 572 return TimeInterval.TI_4_HOURS; 573 } else { 574 return TimeInterval.TI_MANY_HOURS; 575 } 576 } 577 578 /** 579 * Convert the service state into service state proto 580 * 581 * @param serviceState Service state 582 * @return Service state proto 583 */ toServiceStateProto(ServiceState serviceState)584 private TelephonyServiceState toServiceStateProto(ServiceState serviceState) { 585 TelephonyServiceState ssProto = new TelephonyServiceState(); 586 587 ssProto.voiceRoamingType = serviceState.getVoiceRoamingType(); 588 ssProto.dataRoamingType = serviceState.getDataRoamingType(); 589 590 ssProto.voiceOperator = new TelephonyServiceState.TelephonyOperator(); 591 592 if (serviceState.getVoiceOperatorAlphaLong() != null) { 593 ssProto.voiceOperator.alphaLong = serviceState.getVoiceOperatorAlphaLong(); 594 } 595 596 if (serviceState.getVoiceOperatorAlphaShort() != null) { 597 ssProto.voiceOperator.alphaShort = serviceState.getVoiceOperatorAlphaShort(); 598 } 599 600 if (serviceState.getVoiceOperatorNumeric() != null) { 601 ssProto.voiceOperator.numeric = serviceState.getVoiceOperatorNumeric(); 602 } 603 604 ssProto.dataOperator = new TelephonyServiceState.TelephonyOperator(); 605 606 if (serviceState.getDataOperatorAlphaLong() != null) { 607 ssProto.dataOperator.alphaLong = serviceState.getDataOperatorAlphaLong(); 608 } 609 610 if (serviceState.getDataOperatorAlphaShort() != null) { 611 ssProto.dataOperator.alphaShort = serviceState.getDataOperatorAlphaShort(); 612 } 613 614 if (serviceState.getDataOperatorNumeric() != null) { 615 ssProto.dataOperator.numeric = serviceState.getDataOperatorNumeric(); 616 } 617 618 ssProto.voiceRat = serviceState.getRilVoiceRadioTechnology(); 619 ssProto.dataRat = serviceState.getRilDataRadioTechnology(); 620 return ssProto; 621 } 622 623 /** 624 * Annotate the call session with events 625 * 626 * @param timestamp Event timestamp 627 * @param phoneId Phone id 628 * @param eventBuilder Call session event builder 629 */ annotateInProgressCallSession(long timestamp, int phoneId, CallSessionEventBuilder eventBuilder)630 private synchronized void annotateInProgressCallSession(long timestamp, int phoneId, 631 CallSessionEventBuilder eventBuilder) { 632 InProgressCallSession callSession = mInProgressCallSessions.get(phoneId); 633 if (callSession != null) { 634 callSession.addEvent(timestamp, eventBuilder); 635 } 636 } 637 638 /** 639 * Annotate the SMS session with events 640 * 641 * @param timestamp Event timestamp 642 * @param phoneId Phone id 643 * @param eventBuilder SMS session event builder 644 */ annotateInProgressSmsSession(long timestamp, int phoneId, SmsSessionEventBuilder eventBuilder)645 private synchronized void annotateInProgressSmsSession(long timestamp, int phoneId, 646 SmsSessionEventBuilder eventBuilder) { 647 InProgressSmsSession smsSession = mInProgressSmsSessions.get(phoneId); 648 if (smsSession != null) { 649 smsSession.addEvent(timestamp, eventBuilder); 650 } 651 } 652 653 /** 654 * Create the call session if there isn't any existing one 655 * 656 * @param phoneId Phone id 657 * @return The call session 658 */ startNewCallSessionIfNeeded(int phoneId)659 private synchronized InProgressCallSession startNewCallSessionIfNeeded(int phoneId) { 660 InProgressCallSession callSession = mInProgressCallSessions.get(phoneId); 661 if (callSession == null) { 662 if (VDBG) Rlog.v(TAG, "Starting a new call session on phone " + phoneId); 663 callSession = new InProgressCallSession(phoneId); 664 mInProgressCallSessions.append(phoneId, callSession); 665 666 // Insert the latest service state, ims capabilities, and ims connection states as the 667 // base. 668 TelephonyServiceState serviceState = mLastServiceState.get(phoneId); 669 if (serviceState != null) { 670 callSession.addEvent(callSession.startElapsedTimeMs, new CallSessionEventBuilder( 671 TelephonyCallSession.Event.Type.RIL_SERVICE_STATE_CHANGED) 672 .setServiceState(serviceState)); 673 } 674 675 ImsCapabilities imsCapabilities = mLastImsCapabilities.get(phoneId); 676 if (imsCapabilities != null) { 677 callSession.addEvent(callSession.startElapsedTimeMs, new CallSessionEventBuilder( 678 TelephonyCallSession.Event.Type.IMS_CAPABILITIES_CHANGED) 679 .setImsCapabilities(imsCapabilities)); 680 } 681 682 ImsConnectionState imsConnectionState = mLastImsConnectionState.get(phoneId); 683 if (imsConnectionState != null) { 684 callSession.addEvent(callSession.startElapsedTimeMs, new CallSessionEventBuilder( 685 TelephonyCallSession.Event.Type.IMS_CONNECTION_STATE_CHANGED) 686 .setImsConnectionState(imsConnectionState)); 687 } 688 } 689 return callSession; 690 } 691 692 /** 693 * Create the SMS session if there isn't any existing one 694 * 695 * @param phoneId Phone id 696 * @return The SMS session 697 */ startNewSmsSessionIfNeeded(int phoneId)698 private synchronized InProgressSmsSession startNewSmsSessionIfNeeded(int phoneId) { 699 InProgressSmsSession smsSession = mInProgressSmsSessions.get(phoneId); 700 if (smsSession == null) { 701 if (VDBG) Rlog.v(TAG, "Starting a new sms session on phone " + phoneId); 702 smsSession = new InProgressSmsSession(phoneId); 703 mInProgressSmsSessions.append(phoneId, smsSession); 704 705 // Insert the latest service state, ims capabilities, and ims connection state as the 706 // base. 707 TelephonyServiceState serviceState = mLastServiceState.get(phoneId); 708 if (serviceState != null) { 709 smsSession.addEvent(smsSession.startElapsedTimeMs, new SmsSessionEventBuilder( 710 TelephonyCallSession.Event.Type.RIL_SERVICE_STATE_CHANGED) 711 .setServiceState(serviceState)); 712 } 713 714 ImsCapabilities imsCapabilities = mLastImsCapabilities.get(phoneId); 715 if (imsCapabilities != null) { 716 smsSession.addEvent(smsSession.startElapsedTimeMs, new SmsSessionEventBuilder( 717 SmsSession.Event.Type.IMS_CAPABILITIES_CHANGED) 718 .setImsCapabilities(imsCapabilities)); 719 } 720 721 ImsConnectionState imsConnectionState = mLastImsConnectionState.get(phoneId); 722 if (imsConnectionState != null) { 723 smsSession.addEvent(smsSession.startElapsedTimeMs, new SmsSessionEventBuilder( 724 SmsSession.Event.Type.IMS_CONNECTION_STATE_CHANGED) 725 .setImsConnectionState(imsConnectionState)); 726 } 727 } 728 return smsSession; 729 } 730 731 /** 732 * Finish the call session and move it into the completed session 733 * 734 * @param inProgressCallSession The in progress call session 735 */ finishCallSession(InProgressCallSession inProgressCallSession)736 private synchronized void finishCallSession(InProgressCallSession inProgressCallSession) { 737 TelephonyCallSession callSession = new TelephonyCallSession(); 738 callSession.events = new TelephonyCallSession.Event[inProgressCallSession.events.size()]; 739 inProgressCallSession.events.toArray(callSession.events); 740 callSession.startTimeMinutes = inProgressCallSession.startSystemTimeMin; 741 callSession.phoneId = inProgressCallSession.phoneId; 742 callSession.eventsDropped = inProgressCallSession.isEventsDropped(); 743 if (mCompletedCallSessions.size() >= MAX_COMPLETED_CALL_SESSIONS) { 744 mCompletedCallSessions.removeFirst(); 745 } 746 mCompletedCallSessions.add(callSession); 747 mInProgressCallSessions.remove(inProgressCallSession.phoneId); 748 if (VDBG) Rlog.v(TAG, "Call session finished"); 749 } 750 751 /** 752 * Finish the SMS session and move it into the completed session 753 * 754 * @param inProgressSmsSession The in progress SMS session 755 */ finishSmsSessionIfNeeded(InProgressSmsSession inProgressSmsSession)756 private synchronized void finishSmsSessionIfNeeded(InProgressSmsSession inProgressSmsSession) { 757 if (inProgressSmsSession.getNumExpectedResponses() == 0) { 758 SmsSession smsSession = new SmsSession(); 759 smsSession.events = new SmsSession.Event[inProgressSmsSession.events.size()]; 760 inProgressSmsSession.events.toArray(smsSession.events); 761 smsSession.startTimeMinutes = inProgressSmsSession.startSystemTimeMin; 762 smsSession.phoneId = inProgressSmsSession.phoneId; 763 smsSession.eventsDropped = inProgressSmsSession.isEventsDropped(); 764 if (mCompletedSmsSessions.size() >= MAX_COMPLETED_SMS_SESSIONS) { 765 mCompletedSmsSessions.removeFirst(); 766 } 767 mCompletedSmsSessions.add(smsSession); 768 mInProgressSmsSessions.remove(inProgressSmsSession.phoneId); 769 if (VDBG) Rlog.v(TAG, "SMS session finished"); 770 } 771 } 772 773 /** 774 * Add telephony event into the queue 775 * 776 * @param event Telephony event 777 */ addTelephonyEvent(TelephonyEvent event)778 private synchronized void addTelephonyEvent(TelephonyEvent event) { 779 if (mTelephonyEvents.size() >= MAX_TELEPHONY_EVENTS) { 780 mTelephonyEvents.removeFirst(); 781 mTelephonyEventsDropped = true; 782 } 783 mTelephonyEvents.add(event); 784 } 785 786 /** 787 * Write service changed event 788 * 789 * @param phoneId Phone id 790 * @param serviceState Service state 791 */ writeServiceStateChanged(int phoneId, ServiceState serviceState)792 public synchronized void writeServiceStateChanged(int phoneId, ServiceState serviceState) { 793 794 TelephonyEvent event = new TelephonyEventBuilder(phoneId) 795 .setServiceState(toServiceStateProto(serviceState)).build(); 796 797 // If service state doesn't change, we don't log the event. 798 if (mLastServiceState.get(phoneId) != null && 799 Arrays.equals(TelephonyServiceState.toByteArray(mLastServiceState.get(phoneId)), 800 TelephonyServiceState.toByteArray(event.serviceState))) { 801 return; 802 } 803 804 mLastServiceState.put(phoneId, event.serviceState); 805 addTelephonyEvent(event); 806 807 annotateInProgressCallSession(event.timestampMillis, phoneId, 808 new CallSessionEventBuilder( 809 TelephonyCallSession.Event.Type.RIL_SERVICE_STATE_CHANGED) 810 .setServiceState(event.serviceState)); 811 annotateInProgressSmsSession(event.timestampMillis, phoneId, 812 new SmsSessionEventBuilder( 813 SmsSession.Event.Type.RIL_SERVICE_STATE_CHANGED) 814 .setServiceState(event.serviceState)); 815 } 816 817 /** 818 * Write data stall event 819 * 820 * @param phoneId Phone id 821 * @param recoveryAction Data stall recovery action 822 */ writeDataStallEvent(int phoneId, int recoveryAction)823 public void writeDataStallEvent(int phoneId, int recoveryAction) { 824 addTelephonyEvent(new TelephonyEventBuilder(phoneId) 825 .setDataStallRecoveryAction(recoveryAction).build()); 826 } 827 828 /** 829 * Write IMS feature settings changed event 830 * 831 * @param phoneId Phone id 832 * @param feature IMS feature 833 * @param network The IMS network type 834 * @param value The settings. 0 indicates disabled, otherwise enabled. 835 * @param status IMS operation status. See OperationStatusConstants for details. 836 */ writeImsSetFeatureValue(int phoneId, int feature, int network, int value, int status)837 public void writeImsSetFeatureValue(int phoneId, int feature, int network, int value, 838 int status) { 839 TelephonySettings s = new TelephonySettings(); 840 switch (feature) { 841 case ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE: 842 s.isEnhanced4GLteModeEnabled = (value != 0); 843 break; 844 case ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI: 845 s.isWifiCallingEnabled = (value != 0); 846 break; 847 case ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE: 848 s.isVtOverLteEnabled = (value != 0); 849 break; 850 case ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_WIFI: 851 s.isVtOverWifiEnabled = (value != 0); 852 break; 853 } 854 855 // If the settings don't change, we don't log the event. 856 if (mLastSettings.get(phoneId) != null && 857 Arrays.equals(TelephonySettings.toByteArray(mLastSettings.get(phoneId)), 858 TelephonySettings.toByteArray(s))) { 859 return; 860 } 861 862 mLastSettings.put(phoneId, s); 863 864 TelephonyEvent event = new TelephonyEventBuilder(phoneId).setSettings(s).build(); 865 addTelephonyEvent(event); 866 867 annotateInProgressCallSession(event.timestampMillis, phoneId, 868 new CallSessionEventBuilder(TelephonyCallSession.Event.Type.SETTINGS_CHANGED) 869 .setSettings(s)); 870 annotateInProgressSmsSession(event.timestampMillis, phoneId, 871 new SmsSessionEventBuilder(SmsSession.Event.Type.SETTINGS_CHANGED) 872 .setSettings(s)); 873 } 874 875 /** 876 * Write the preferred network settings changed event 877 * 878 * @param phoneId Phone id 879 * @param networkType The preferred network 880 */ writeSetPreferredNetworkType(int phoneId, int networkType)881 public void writeSetPreferredNetworkType(int phoneId, int networkType) { 882 TelephonySettings s = new TelephonySettings(); 883 s.preferredNetworkMode = networkType + 1; 884 885 // If the settings don't change, we don't log the event. 886 if (mLastSettings.get(phoneId) != null && 887 Arrays.equals(TelephonySettings.toByteArray(mLastSettings.get(phoneId)), 888 TelephonySettings.toByteArray(s))) { 889 return; 890 } 891 892 mLastSettings.put(phoneId, s); 893 894 addTelephonyEvent(new TelephonyEventBuilder(phoneId).setSettings(s).build()); 895 } 896 897 /** 898 * Write the IMS connection state changed event 899 * 900 * @param phoneId Phone id 901 * @param state IMS connection state 902 * @param reasonInfo The reason info. Only used for disconnected state. 903 */ writeOnImsConnectionState(int phoneId, int state, ImsReasonInfo reasonInfo)904 public synchronized void writeOnImsConnectionState(int phoneId, int state, 905 ImsReasonInfo reasonInfo) { 906 ImsConnectionState imsState = new ImsConnectionState(); 907 imsState.state = state; 908 909 if (reasonInfo != null) { 910 TelephonyProto.ImsReasonInfo ri = new TelephonyProto.ImsReasonInfo(); 911 912 ri.reasonCode = reasonInfo.getCode(); 913 ri.extraCode = reasonInfo.getExtraCode(); 914 String extraMessage = reasonInfo.getExtraMessage(); 915 if (extraMessage != null) { 916 ri.extraMessage = extraMessage; 917 } 918 919 imsState.reasonInfo = ri; 920 } 921 922 // If the connection state does not change, do not log it. 923 if (mLastImsConnectionState.get(phoneId) != null && 924 Arrays.equals(ImsConnectionState.toByteArray(mLastImsConnectionState.get(phoneId)), 925 ImsConnectionState.toByteArray(imsState))) { 926 return; 927 } 928 929 mLastImsConnectionState.put(phoneId, imsState); 930 931 TelephonyEvent event = new TelephonyEventBuilder(phoneId) 932 .setImsConnectionState(imsState).build(); 933 addTelephonyEvent(event); 934 935 annotateInProgressCallSession(event.timestampMillis, phoneId, 936 new CallSessionEventBuilder( 937 TelephonyCallSession.Event.Type.IMS_CONNECTION_STATE_CHANGED) 938 .setImsConnectionState(event.imsConnectionState)); 939 annotateInProgressSmsSession(event.timestampMillis, phoneId, 940 new SmsSessionEventBuilder( 941 SmsSession.Event.Type.IMS_CONNECTION_STATE_CHANGED) 942 .setImsConnectionState(event.imsConnectionState)); 943 } 944 945 /** 946 * Write the IMS capabilities changed event 947 * 948 * @param phoneId Phone id 949 * @param capabilities IMS capabilities array 950 */ writeOnImsCapabilities(int phoneId, boolean[] capabilities)951 public synchronized void writeOnImsCapabilities(int phoneId, boolean[] capabilities) { 952 ImsCapabilities cap = new ImsCapabilities(); 953 954 cap.voiceOverLte = capabilities[0]; 955 cap.videoOverLte = capabilities[1]; 956 cap.voiceOverWifi = capabilities[2]; 957 cap.videoOverWifi = capabilities[3]; 958 cap.utOverLte = capabilities[4]; 959 cap.utOverWifi = capabilities[5]; 960 961 TelephonyEvent event = new TelephonyEventBuilder(phoneId).setImsCapabilities(cap).build(); 962 963 // If the capabilities don't change, we don't log the event. 964 if (mLastImsCapabilities.get(phoneId) != null && 965 Arrays.equals(ImsCapabilities.toByteArray(mLastImsCapabilities.get(phoneId)), 966 ImsCapabilities.toByteArray(cap))) { 967 return; 968 } 969 970 mLastImsCapabilities.put(phoneId, cap); 971 addTelephonyEvent(event); 972 973 annotateInProgressCallSession(event.timestampMillis, phoneId, 974 new CallSessionEventBuilder( 975 TelephonyCallSession.Event.Type.IMS_CAPABILITIES_CHANGED) 976 .setImsCapabilities(event.imsCapabilities)); 977 annotateInProgressSmsSession(event.timestampMillis, phoneId, 978 new SmsSessionEventBuilder( 979 SmsSession.Event.Type.IMS_CAPABILITIES_CHANGED) 980 .setImsCapabilities(event.imsCapabilities)); 981 } 982 983 /** 984 * Convert PDP type into the enumeration 985 * 986 * @param type PDP type 987 * @return The proto defined enumeration 988 */ toPdpType(String type)989 private int toPdpType(String type) { 990 switch (type) { 991 case "IP": 992 return PDP_TYPE_IP; 993 case "IPV6": 994 return PDP_TYPE_IPV6; 995 case "IPV4V6": 996 return PDP_TYPE_IPV4V6; 997 case "PPP": 998 return PDP_TYPE_PPP; 999 } 1000 Rlog.e(TAG, "Unknown type: " + type); 1001 return PDP_UNKNOWN; 1002 } 1003 1004 /** 1005 * Write setup data call event 1006 * 1007 * @param phoneId Phone id 1008 * @param rilSerial RIL request serial number 1009 * @param radioTechnology The data call RAT 1010 * @param profile Data profile 1011 * @param apn APN in string 1012 * @param authType Authentication type 1013 * @param protocol Data connection protocol 1014 */ writeRilSetupDataCall(int phoneId, int rilSerial, int radioTechnology, int profile, String apn, int authType, String protocol)1015 public void writeRilSetupDataCall(int phoneId, int rilSerial, int radioTechnology, int profile, 1016 String apn, int authType, String protocol) { 1017 1018 RilSetupDataCall setupDataCall = new RilSetupDataCall(); 1019 setupDataCall.rat = radioTechnology; 1020 setupDataCall.dataProfile = profile + 1; // off by 1 between proto and RIL constants. 1021 if (apn != null) { 1022 setupDataCall.apn = apn; 1023 } 1024 if (protocol != null) { 1025 setupDataCall.type = toPdpType(protocol); 1026 } 1027 1028 addTelephonyEvent(new TelephonyEventBuilder(phoneId).setSetupDataCall( 1029 setupDataCall).build()); 1030 } 1031 1032 /** 1033 * Write data call deactivate event 1034 * 1035 * @param phoneId Phone id 1036 * @param rilSerial RIL request serial number 1037 * @param cid call id 1038 * @param reason Deactivate reason 1039 */ writeRilDeactivateDataCall(int phoneId, int rilSerial, int cid, int reason)1040 public void writeRilDeactivateDataCall(int phoneId, int rilSerial, int cid, int reason) { 1041 1042 RilDeactivateDataCall deactivateDataCall = new RilDeactivateDataCall(); 1043 deactivateDataCall.cid = cid; 1044 deactivateDataCall.reason = reason + 1; 1045 1046 addTelephonyEvent(new TelephonyEventBuilder(phoneId).setDeactivateDataCall( 1047 deactivateDataCall).build()); 1048 } 1049 1050 /** 1051 * Write get data call list event 1052 * 1053 * @param phoneId Phone id 1054 * @param dcsList Data call list 1055 */ writeRilDataCallList(int phoneId, ArrayList<DataCallResponse> dcsList)1056 public void writeRilDataCallList(int phoneId, ArrayList<DataCallResponse> dcsList) { 1057 1058 RilDataCall[] dataCalls = new RilDataCall[dcsList.size()]; 1059 1060 for (int i = 0; i < dcsList.size(); i++) { 1061 dataCalls[i] = new RilDataCall(); 1062 dataCalls[i].cid = dcsList.get(i).cid; 1063 if (!TextUtils.isEmpty(dcsList.get(i).ifname)) { 1064 dataCalls[i].iframe = dcsList.get(i).ifname; 1065 } 1066 if (!TextUtils.isEmpty(dcsList.get(i).type)) { 1067 dataCalls[i].type = toPdpType(dcsList.get(i).type); 1068 } 1069 } 1070 1071 addTelephonyEvent(new TelephonyEventBuilder(phoneId).setDataCalls(dataCalls).build()); 1072 } 1073 1074 /** 1075 * Write CS call list event 1076 * 1077 * @param phoneId Phone id 1078 * @param connections Array of GsmCdmaConnection objects 1079 */ writeRilCallList(int phoneId, ArrayList<GsmCdmaConnection> connections)1080 public void writeRilCallList(int phoneId, ArrayList<GsmCdmaConnection> connections) { 1081 if (VDBG) { 1082 Rlog.v(TAG, "Logging CallList Changed Connections Size = " + connections.size()); 1083 } 1084 InProgressCallSession callSession = startNewCallSessionIfNeeded(phoneId); 1085 if (callSession == null) { 1086 Rlog.e(TAG, "writeRilCallList: Call session is missing"); 1087 } else { 1088 RilCall[] calls = convertConnectionsToRilCalls(connections); 1089 callSession.addEvent( 1090 new CallSessionEventBuilder( 1091 TelephonyCallSession.Event.Type.RIL_CALL_LIST_CHANGED) 1092 .setRilCalls(calls) 1093 ); 1094 if (VDBG) Rlog.v(TAG, "Logged Call list changed"); 1095 if (callSession.isPhoneIdle() && disconnectReasonsKnown(calls)) { 1096 finishCallSession(callSession); 1097 } 1098 } 1099 } 1100 disconnectReasonsKnown(RilCall[] calls)1101 private boolean disconnectReasonsKnown(RilCall[] calls) { 1102 for (RilCall call : calls) { 1103 if (call.callEndReason == 0) return false; 1104 } 1105 return true; 1106 } 1107 convertConnectionsToRilCalls(ArrayList<GsmCdmaConnection> mConnections)1108 private RilCall[] convertConnectionsToRilCalls(ArrayList<GsmCdmaConnection> mConnections) { 1109 RilCall[] calls = new RilCall[mConnections.size()]; 1110 for (int i = 0; i < mConnections.size(); i++) { 1111 calls[i] = new RilCall(); 1112 calls[i].index = i; 1113 convertConnectionToRilCall(mConnections.get(i), calls[i]); 1114 } 1115 return calls; 1116 } 1117 convertConnectionToRilCall(GsmCdmaConnection conn, RilCall call)1118 private void convertConnectionToRilCall(GsmCdmaConnection conn, RilCall call) { 1119 if (conn.isIncoming()) { 1120 call.type = Type.MT; 1121 } else { 1122 call.type = Type.MO; 1123 } 1124 switch (conn.getState()) { 1125 case IDLE: 1126 call.state = CallState.CALL_IDLE; 1127 break; 1128 case ACTIVE: 1129 call.state = CallState.CALL_ACTIVE; 1130 break; 1131 case HOLDING: 1132 call.state = CallState.CALL_HOLDING; 1133 break; 1134 case DIALING: 1135 call.state = CallState.CALL_DIALING; 1136 break; 1137 case ALERTING: 1138 call.state = CallState.CALL_ALERTING; 1139 break; 1140 case INCOMING: 1141 call.state = CallState.CALL_INCOMING; 1142 break; 1143 case WAITING: 1144 call.state = CallState.CALL_WAITING; 1145 break; 1146 case DISCONNECTED: 1147 call.state = CallState.CALL_DISCONNECTED; 1148 break; 1149 case DISCONNECTING: 1150 call.state = CallState.CALL_DISCONNECTING; 1151 break; 1152 default: 1153 call.state = CallState.CALL_UNKNOWN; 1154 break; 1155 } 1156 call.callEndReason = conn.getDisconnectCause(); 1157 call.isMultiparty = conn.isMultiparty(); 1158 } 1159 1160 /** 1161 * Write dial event 1162 * 1163 * @param phoneId Phone id 1164 * @param conn Connection object created to track this call 1165 * @param clirMode CLIR (Calling Line Identification Restriction) mode 1166 * @param uusInfo User-to-User signaling Info 1167 */ writeRilDial(int phoneId, GsmCdmaConnection conn, int clirMode, UUSInfo uusInfo)1168 public void writeRilDial(int phoneId, GsmCdmaConnection conn, int clirMode, UUSInfo uusInfo) { 1169 1170 InProgressCallSession callSession = startNewCallSessionIfNeeded(phoneId); 1171 if (VDBG) Rlog.v(TAG, "Logging Dial Connection = " + conn); 1172 if (callSession == null) { 1173 Rlog.e(TAG, "writeRilDial: Call session is missing"); 1174 } else { 1175 RilCall[] calls = new RilCall[1]; 1176 calls[0] = new RilCall(); 1177 calls[0].index = -1; 1178 convertConnectionToRilCall(conn, calls[0]); 1179 callSession.addEvent(callSession.startElapsedTimeMs, 1180 new CallSessionEventBuilder(TelephonyCallSession.Event.Type.RIL_REQUEST) 1181 .setRilRequest(TelephonyCallSession.Event.RilRequest.RIL_REQUEST_DIAL) 1182 .setRilCalls(calls)); 1183 if (VDBG) Rlog.v(TAG, "Logged Dial event"); 1184 } 1185 } 1186 1187 /** 1188 * Write incoming call event 1189 * 1190 * @param phoneId Phone id 1191 * @param response Unused today 1192 */ writeRilCallRing(int phoneId, char[] response)1193 public void writeRilCallRing(int phoneId, char[] response) { 1194 InProgressCallSession callSession = startNewCallSessionIfNeeded(phoneId); 1195 1196 callSession.addEvent(callSession.startElapsedTimeMs, 1197 new CallSessionEventBuilder(TelephonyCallSession.Event.Type.RIL_CALL_RING)); 1198 } 1199 1200 /** 1201 * Write call hangup event 1202 * 1203 * @param phoneId Phone id 1204 * @param conn Connection object associated with the call that is being hung-up 1205 * @param callId Call id 1206 */ writeRilHangup(int phoneId, GsmCdmaConnection conn, int callId)1207 public void writeRilHangup(int phoneId, GsmCdmaConnection conn, int callId) { 1208 InProgressCallSession callSession = mInProgressCallSessions.get(phoneId); 1209 if (callSession == null) { 1210 Rlog.e(TAG, "writeRilHangup: Call session is missing"); 1211 } else { 1212 RilCall[] calls = new RilCall[1]; 1213 calls[0] = new RilCall(); 1214 calls[0].index = callId; 1215 convertConnectionToRilCall(conn, calls[0]); 1216 callSession.addEvent( 1217 new CallSessionEventBuilder(TelephonyCallSession.Event.Type.RIL_REQUEST) 1218 .setRilRequest(TelephonyCallSession.Event.RilRequest.RIL_REQUEST_HANGUP) 1219 .setRilCalls(calls)); 1220 if (VDBG) Rlog.v(TAG, "Logged Hangup event"); 1221 } 1222 } 1223 1224 /** 1225 * Write call answer event 1226 * 1227 * @param phoneId Phone id 1228 * @param rilSerial RIL request serial number 1229 */ writeRilAnswer(int phoneId, int rilSerial)1230 public void writeRilAnswer(int phoneId, int rilSerial) { 1231 InProgressCallSession callSession = mInProgressCallSessions.get(phoneId); 1232 if (callSession == null) { 1233 Rlog.e(TAG, "writeRilAnswer: Call session is missing"); 1234 } else { 1235 callSession.addEvent( 1236 new CallSessionEventBuilder(TelephonyCallSession.Event.Type.RIL_REQUEST) 1237 .setRilRequest(TelephonyCallSession.Event.RilRequest.RIL_REQUEST_ANSWER) 1238 .setRilRequestId(rilSerial)); 1239 } 1240 } 1241 1242 /** 1243 * Write IMS call SRVCC event 1244 * 1245 * @param phoneId Phone id 1246 * @param rilSrvccState SRVCC state 1247 */ writeRilSrvcc(int phoneId, int rilSrvccState)1248 public void writeRilSrvcc(int phoneId, int rilSrvccState) { 1249 InProgressCallSession callSession = mInProgressCallSessions.get(phoneId); 1250 if (callSession == null) { 1251 Rlog.e(TAG, "writeRilSrvcc: Call session is missing"); 1252 } else { 1253 callSession.addEvent( 1254 new CallSessionEventBuilder(TelephonyCallSession.Event.Type.RIL_CALL_SRVCC) 1255 .setSrvccState(rilSrvccState + 1)); 1256 } 1257 } 1258 1259 /** 1260 * Convert RIL request into proto defined RIL request 1261 * 1262 * @param r RIL request 1263 * @return RIL request defined in call session proto 1264 */ toCallSessionRilRequest(int r)1265 private int toCallSessionRilRequest(int r) { 1266 switch (r) { 1267 case RILConstants.RIL_REQUEST_DIAL: 1268 return TelephonyCallSession.Event.RilRequest.RIL_REQUEST_DIAL; 1269 1270 case RILConstants.RIL_REQUEST_ANSWER: 1271 return TelephonyCallSession.Event.RilRequest.RIL_REQUEST_ANSWER; 1272 1273 case RILConstants.RIL_REQUEST_HANGUP: 1274 case RILConstants.RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND: 1275 case RILConstants.RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND: 1276 return TelephonyCallSession.Event.RilRequest.RIL_REQUEST_HANGUP; 1277 1278 case RILConstants.RIL_REQUEST_SET_CALL_WAITING: 1279 return TelephonyCallSession.Event.RilRequest.RIL_REQUEST_SET_CALL_WAITING; 1280 1281 case RILConstants.RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE: 1282 return TelephonyCallSession.Event.RilRequest.RIL_REQUEST_SWITCH_HOLDING_AND_ACTIVE; 1283 1284 case RILConstants.RIL_REQUEST_CDMA_FLASH: 1285 return TelephonyCallSession.Event.RilRequest.RIL_REQUEST_CDMA_FLASH; 1286 1287 case RILConstants.RIL_REQUEST_CONFERENCE: 1288 return TelephonyCallSession.Event.RilRequest.RIL_REQUEST_CONFERENCE; 1289 } 1290 Rlog.e(TAG, "Unknown RIL request: " + r); 1291 return TelephonyCallSession.Event.RilRequest.RIL_REQUEST_UNKNOWN; 1292 } 1293 1294 /** 1295 * Write setup data call response event 1296 * 1297 * @param phoneId Phone id 1298 * @param rilSerial RIL request serial number 1299 * @param rilError RIL error 1300 * @param rilRequest RIL request 1301 * @param response Data call response 1302 */ writeOnSetupDataCallResponse(int phoneId, int rilSerial, int rilError, int rilRequest, DataCallResponse response)1303 private void writeOnSetupDataCallResponse(int phoneId, int rilSerial, int rilError, 1304 int rilRequest, DataCallResponse response) { 1305 1306 RilSetupDataCallResponse setupDataCallResponse = new RilSetupDataCallResponse(); 1307 RilDataCall dataCall = new RilDataCall(); 1308 1309 if (response != null) { 1310 setupDataCallResponse.status = 1311 (response.status == 0 ? RilDataCallFailCause.PDP_FAIL_NONE : response.status); 1312 setupDataCallResponse.suggestedRetryTimeMillis = response.suggestedRetryTime; 1313 1314 dataCall.cid = response.cid; 1315 if (!TextUtils.isEmpty(response.type)) { 1316 dataCall.type = toPdpType(response.type); 1317 } 1318 1319 if (!TextUtils.isEmpty(response.ifname)) { 1320 dataCall.iframe = response.ifname; 1321 } 1322 } 1323 setupDataCallResponse.call = dataCall; 1324 1325 addTelephonyEvent(new TelephonyEventBuilder(phoneId) 1326 .setSetupDataCallResponse(setupDataCallResponse).build()); 1327 } 1328 1329 /** 1330 * Write call related solicited response event 1331 * 1332 * @param phoneId Phone id 1333 * @param rilSerial RIL request serial number 1334 * @param rilError RIL error 1335 * @param rilRequest RIL request 1336 */ writeOnCallSolicitedResponse(int phoneId, int rilSerial, int rilError, int rilRequest)1337 private void writeOnCallSolicitedResponse(int phoneId, int rilSerial, int rilError, 1338 int rilRequest) { 1339 InProgressCallSession callSession = mInProgressCallSessions.get(phoneId); 1340 if (callSession == null) { 1341 Rlog.e(TAG, "writeOnCallSolicitedResponse: Call session is missing"); 1342 } else { 1343 callSession.addEvent(new CallSessionEventBuilder( 1344 TelephonyCallSession.Event.Type.RIL_RESPONSE) 1345 .setRilRequest(toCallSessionRilRequest(rilRequest)) 1346 .setRilRequestId(rilSerial) 1347 .setRilError(rilError + 1)); 1348 } 1349 } 1350 1351 /** 1352 * Write SMS related solicited response event 1353 * 1354 * @param phoneId Phone id 1355 * @param rilSerial RIL request serial number 1356 * @param rilError RIL error 1357 * @param response SMS response 1358 */ writeOnSmsSolicitedResponse(int phoneId, int rilSerial, int rilError, SmsResponse response)1359 private synchronized void writeOnSmsSolicitedResponse(int phoneId, int rilSerial, int rilError, 1360 SmsResponse response) { 1361 1362 InProgressSmsSession smsSession = mInProgressSmsSessions.get(phoneId); 1363 if (smsSession == null) { 1364 Rlog.e(TAG, "SMS session is missing"); 1365 } else { 1366 1367 int errorCode = 0; 1368 if (response != null) { 1369 errorCode = response.mErrorCode; 1370 } 1371 1372 smsSession.addEvent(new SmsSessionEventBuilder( 1373 SmsSession.Event.Type.SMS_SEND_RESULT) 1374 .setErrorCode(errorCode) 1375 .setRilErrno(rilError + 1) 1376 .setRilRequestId(rilSerial) 1377 ); 1378 1379 smsSession.decreaseExpectedResponse(); 1380 finishSmsSessionIfNeeded(smsSession); 1381 } 1382 } 1383 1384 /** 1385 * Write deactivate data call response event 1386 * 1387 * @param phoneId Phone id 1388 * @param rilError RIL error 1389 */ writeOnDeactivateDataCallResponse(int phoneId, int rilError)1390 private void writeOnDeactivateDataCallResponse(int phoneId, int rilError) { 1391 addTelephonyEvent(new TelephonyEventBuilder(phoneId) 1392 .setDeactivateDataCallResponse(rilError + 1).build()); 1393 } 1394 1395 /** 1396 * Write RIL solicited response event 1397 * 1398 * @param phoneId Phone id 1399 * @param rilSerial RIL request serial number 1400 * @param rilError RIL error 1401 * @param rilRequest RIL request 1402 * @param ret The returned RIL response 1403 */ writeOnRilSolicitedResponse(int phoneId, int rilSerial, int rilError, int rilRequest, Object ret)1404 public void writeOnRilSolicitedResponse(int phoneId, int rilSerial, int rilError, 1405 int rilRequest, Object ret) { 1406 switch (rilRequest) { 1407 case RIL_REQUEST_SETUP_DATA_CALL: 1408 DataCallResponse dataCall = (DataCallResponse) ret; 1409 writeOnSetupDataCallResponse(phoneId, rilSerial, rilError, rilRequest, dataCall); 1410 break; 1411 case RIL_REQUEST_DEACTIVATE_DATA_CALL: 1412 writeOnDeactivateDataCallResponse(phoneId, rilError); 1413 break; 1414 case RIL_REQUEST_HANGUP: 1415 case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND: 1416 case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND: 1417 case RIL_REQUEST_DIAL: 1418 case RIL_REQUEST_ANSWER: 1419 writeOnCallSolicitedResponse(phoneId, rilSerial, rilError, rilRequest); 1420 break; 1421 case RIL_REQUEST_SEND_SMS: 1422 case RIL_REQUEST_SEND_SMS_EXPECT_MORE: 1423 case RIL_REQUEST_CDMA_SEND_SMS: 1424 case RIL_REQUEST_IMS_SEND_SMS: 1425 SmsResponse smsResponse = (SmsResponse) ret; 1426 writeOnSmsSolicitedResponse(phoneId, rilSerial, rilError, smsResponse); 1427 break; 1428 } 1429 } 1430 1431 /** 1432 * Write phone state changed event 1433 * 1434 * @param phoneId Phone id 1435 * @param phoneState Phone state. See PhoneConstants.State for the details. 1436 */ writePhoneState(int phoneId, PhoneConstants.State phoneState)1437 public void writePhoneState(int phoneId, PhoneConstants.State phoneState) { 1438 int state; 1439 switch (phoneState) { 1440 case IDLE: 1441 state = TelephonyCallSession.Event.PhoneState.STATE_IDLE; 1442 break; 1443 case RINGING: 1444 state = TelephonyCallSession.Event.PhoneState.STATE_RINGING; 1445 break; 1446 case OFFHOOK: 1447 state = TelephonyCallSession.Event.PhoneState.STATE_OFFHOOK; 1448 break; 1449 default: 1450 state = TelephonyCallSession.Event.PhoneState.STATE_UNKNOWN; 1451 break; 1452 } 1453 1454 InProgressCallSession callSession = mInProgressCallSessions.get(phoneId); 1455 if (callSession == null) { 1456 Rlog.e(TAG, "writePhoneState: Call session is missing"); 1457 } else { 1458 // For CS Calls Finish the Call Session after Receiving the Last Call Fail Cause 1459 // For IMS calls we receive the Disconnect Cause along with Call End event. 1460 // So we can finish the call session here. 1461 callSession.setLastKnownPhoneState(state); 1462 if ((state == TelephonyCallSession.Event.PhoneState.STATE_IDLE) 1463 && (!callSession.containsCsCalls())) { 1464 finishCallSession(callSession); 1465 } 1466 callSession.addEvent(new CallSessionEventBuilder( 1467 TelephonyCallSession.Event.Type.PHONE_STATE_CHANGED) 1468 .setPhoneState(state)); 1469 } 1470 } 1471 1472 /** 1473 * Extracts the call ID from an ImsSession. 1474 * 1475 * @param session The session. 1476 * @return The call ID for the session, or -1 if none was found. 1477 */ getCallId(ImsCallSession session)1478 private int getCallId(ImsCallSession session) { 1479 if (session == null) { 1480 return -1; 1481 } 1482 1483 try { 1484 return Integer.parseInt(session.getCallId()); 1485 } catch (NumberFormatException nfe) { 1486 return -1; 1487 } 1488 } 1489 1490 /** 1491 * Write IMS call state changed event 1492 * 1493 * @param phoneId Phone id 1494 * @param session IMS call session 1495 * @param callState IMS call state 1496 */ writeImsCallState(int phoneId, ImsCallSession session, ImsPhoneCall.State callState)1497 public void writeImsCallState(int phoneId, ImsCallSession session, 1498 ImsPhoneCall.State callState) { 1499 int state; 1500 switch (callState) { 1501 case IDLE: 1502 state = TelephonyCallSession.Event.CallState.CALL_IDLE; break; 1503 case ACTIVE: 1504 state = TelephonyCallSession.Event.CallState.CALL_ACTIVE; break; 1505 case HOLDING: 1506 state = TelephonyCallSession.Event.CallState.CALL_HOLDING; break; 1507 case DIALING: 1508 state = TelephonyCallSession.Event.CallState.CALL_DIALING; break; 1509 case ALERTING: 1510 state = TelephonyCallSession.Event.CallState.CALL_ALERTING; break; 1511 case INCOMING: 1512 state = TelephonyCallSession.Event.CallState.CALL_INCOMING; break; 1513 case WAITING: 1514 state = TelephonyCallSession.Event.CallState.CALL_WAITING; break; 1515 case DISCONNECTED: 1516 state = TelephonyCallSession.Event.CallState.CALL_DISCONNECTED; break; 1517 case DISCONNECTING: 1518 state = TelephonyCallSession.Event.CallState.CALL_DISCONNECTING; break; 1519 default: 1520 state = TelephonyCallSession.Event.CallState.CALL_UNKNOWN; break; 1521 } 1522 1523 InProgressCallSession callSession = mInProgressCallSessions.get(phoneId); 1524 if (callSession == null) { 1525 Rlog.e(TAG, "Call session is missing"); 1526 } else { 1527 callSession.addEvent(new CallSessionEventBuilder( 1528 TelephonyCallSession.Event.Type.IMS_CALL_STATE_CHANGED) 1529 .setCallIndex(getCallId(session)) 1530 .setCallState(state)); 1531 } 1532 } 1533 1534 /** 1535 * Write IMS call start event 1536 * 1537 * @param phoneId Phone id 1538 * @param session IMS call session 1539 */ writeOnImsCallStart(int phoneId, ImsCallSession session)1540 public void writeOnImsCallStart(int phoneId, ImsCallSession session) { 1541 InProgressCallSession callSession = startNewCallSessionIfNeeded(phoneId); 1542 1543 callSession.addEvent( 1544 new CallSessionEventBuilder(TelephonyCallSession.Event.Type.IMS_COMMAND) 1545 .setCallIndex(getCallId(session)) 1546 .setImsCommand(TelephonyCallSession.Event.ImsCommand.IMS_CMD_START)); 1547 } 1548 1549 /** 1550 * Write IMS incoming call event 1551 * 1552 * @param phoneId Phone id 1553 * @param session IMS call session 1554 */ writeOnImsCallReceive(int phoneId, ImsCallSession session)1555 public void writeOnImsCallReceive(int phoneId, ImsCallSession session) { 1556 InProgressCallSession callSession = startNewCallSessionIfNeeded(phoneId); 1557 1558 callSession.addEvent( 1559 new CallSessionEventBuilder(TelephonyCallSession.Event.Type.IMS_CALL_RECEIVE) 1560 .setCallIndex(getCallId(session))); 1561 } 1562 1563 /** 1564 * Write IMS command event 1565 * 1566 * @param phoneId Phone id 1567 * @param session IMS call session 1568 * @param command IMS command 1569 */ writeOnImsCommand(int phoneId, ImsCallSession session, int command)1570 public void writeOnImsCommand(int phoneId, ImsCallSession session, int command) { 1571 1572 InProgressCallSession callSession = mInProgressCallSessions.get(phoneId); 1573 if (callSession == null) { 1574 Rlog.e(TAG, "Call session is missing"); 1575 } else { 1576 callSession.addEvent( 1577 new CallSessionEventBuilder(TelephonyCallSession.Event.Type.IMS_COMMAND) 1578 .setCallIndex(getCallId(session)) 1579 .setImsCommand(command)); 1580 } 1581 } 1582 1583 /** 1584 * Convert IMS reason info into proto 1585 * 1586 * @param reasonInfo IMS reason info 1587 * @return Converted proto 1588 */ toImsReasonInfoProto(ImsReasonInfo reasonInfo)1589 private TelephonyProto.ImsReasonInfo toImsReasonInfoProto(ImsReasonInfo reasonInfo) { 1590 TelephonyProto.ImsReasonInfo ri = new TelephonyProto.ImsReasonInfo(); 1591 if (reasonInfo != null) { 1592 ri.reasonCode = reasonInfo.getCode(); 1593 ri.extraCode = reasonInfo.getExtraCode(); 1594 String extraMessage = reasonInfo.getExtraMessage(); 1595 if (extraMessage != null) { 1596 ri.extraMessage = extraMessage; 1597 } 1598 } 1599 return ri; 1600 } 1601 1602 /** 1603 * Write IMS call end event 1604 * 1605 * @param phoneId Phone id 1606 * @param session IMS call session 1607 * @param reasonInfo Call end reason 1608 */ writeOnImsCallTerminated(int phoneId, ImsCallSession session, ImsReasonInfo reasonInfo)1609 public void writeOnImsCallTerminated(int phoneId, ImsCallSession session, 1610 ImsReasonInfo reasonInfo) { 1611 InProgressCallSession callSession = mInProgressCallSessions.get(phoneId); 1612 if (callSession == null) { 1613 Rlog.e(TAG, "Call session is missing"); 1614 } else { 1615 callSession.addEvent( 1616 new CallSessionEventBuilder(TelephonyCallSession.Event.Type.IMS_CALL_TERMINATED) 1617 .setCallIndex(getCallId(session)) 1618 .setImsReasonInfo(toImsReasonInfoProto(reasonInfo))); 1619 } 1620 } 1621 1622 /** 1623 * Write IMS call hangover event 1624 * 1625 * @param phoneId Phone id 1626 * @param eventType hangover type 1627 * @param session IMS call session 1628 * @param srcAccessTech Hangover starting RAT 1629 * @param targetAccessTech Hangover destination RAT 1630 * @param reasonInfo Hangover reason 1631 */ writeOnImsCallHandoverEvent(int phoneId, int eventType, ImsCallSession session, int srcAccessTech, int targetAccessTech, ImsReasonInfo reasonInfo)1632 public void writeOnImsCallHandoverEvent(int phoneId, int eventType, ImsCallSession session, 1633 int srcAccessTech, int targetAccessTech, 1634 ImsReasonInfo reasonInfo) { 1635 InProgressCallSession callSession = mInProgressCallSessions.get(phoneId); 1636 if (callSession == null) { 1637 Rlog.e(TAG, "Call session is missing"); 1638 } else { 1639 callSession.addEvent( 1640 new CallSessionEventBuilder(eventType) 1641 .setCallIndex(getCallId(session)) 1642 .setSrcAccessTech(srcAccessTech) 1643 .setTargetAccessTech(targetAccessTech) 1644 .setImsReasonInfo(toImsReasonInfoProto(reasonInfo))); 1645 } 1646 } 1647 1648 /** 1649 * Write Send SMS event 1650 * 1651 * @param phoneId Phone id 1652 * @param rilSerial RIL request serial number 1653 * @param tech SMS RAT 1654 * @param format SMS format. Either 3GPP or 3GPP2. 1655 */ writeRilSendSms(int phoneId, int rilSerial, int tech, int format)1656 public void writeRilSendSms(int phoneId, int rilSerial, int tech, int format) { 1657 InProgressSmsSession smsSession = startNewSmsSessionIfNeeded(phoneId); 1658 1659 smsSession.addEvent(new SmsSessionEventBuilder(SmsSession.Event.Type.SMS_SEND) 1660 .setTech(tech) 1661 .setRilRequestId(rilSerial) 1662 .setFormat(format) 1663 ); 1664 1665 smsSession.increaseExpectedResponse(); 1666 } 1667 1668 /** 1669 * Write incoming SMS event 1670 * 1671 * @param phoneId Phone id 1672 * @param tech SMS RAT 1673 * @param format SMS format. Either 3GPP or 3GPP2. 1674 */ writeRilNewSms(int phoneId, int tech, int format)1675 public void writeRilNewSms(int phoneId, int tech, int format) { 1676 InProgressSmsSession smsSession = startNewSmsSessionIfNeeded(phoneId); 1677 1678 smsSession.addEvent(new SmsSessionEventBuilder(SmsSession.Event.Type.SMS_RECEIVED) 1679 .setTech(tech) 1680 .setFormat(format) 1681 ); 1682 1683 finishSmsSessionIfNeeded(smsSession); 1684 } 1685 1686 /** 1687 * Write NITZ event 1688 * 1689 * @param phoneId Phone id 1690 * @param timestamp NITZ time in milliseconds 1691 */ writeNITZEvent(int phoneId, long timestamp)1692 public void writeNITZEvent(int phoneId, long timestamp) { 1693 TelephonyEvent event = new TelephonyEventBuilder(phoneId).setNITZ(timestamp).build(); 1694 addTelephonyEvent(event); 1695 1696 annotateInProgressCallSession(event.timestampMillis, phoneId, 1697 new CallSessionEventBuilder( 1698 TelephonyCallSession.Event.Type.NITZ_TIME) 1699 .setNITZ(timestamp)); 1700 } 1701 1702 /** 1703 * Write Modem Restart event 1704 * 1705 * @param phoneId Phone id 1706 * @param reason Reason for the modem reset. 1707 */ writeModemRestartEvent(int phoneId, String reason)1708 public void writeModemRestartEvent(int phoneId, String reason) { 1709 final ModemRestart modemRestart = new ModemRestart(); 1710 String basebandVersion = Build.getRadioVersion(); 1711 if (basebandVersion != null) modemRestart.basebandVersion = basebandVersion; 1712 if (reason != null) modemRestart.reason = reason; 1713 TelephonyEvent event = new TelephonyEventBuilder(phoneId).setModemRestart( 1714 modemRestart).build(); 1715 addTelephonyEvent(event); 1716 } 1717 1718 //TODO: Expand the proto in the future writeOnImsCallProgressing(int phoneId, ImsCallSession session)1719 public void writeOnImsCallProgressing(int phoneId, ImsCallSession session) {} writeOnImsCallStarted(int phoneId, ImsCallSession session)1720 public void writeOnImsCallStarted(int phoneId, ImsCallSession session) {} writeOnImsCallStartFailed(int phoneId, ImsCallSession session, ImsReasonInfo reasonInfo)1721 public void writeOnImsCallStartFailed(int phoneId, ImsCallSession session, 1722 ImsReasonInfo reasonInfo) {} writeOnImsCallHeld(int phoneId, ImsCallSession session)1723 public void writeOnImsCallHeld(int phoneId, ImsCallSession session) {} writeOnImsCallHoldReceived(int phoneId, ImsCallSession session)1724 public void writeOnImsCallHoldReceived(int phoneId, ImsCallSession session) {} writeOnImsCallHoldFailed(int phoneId, ImsCallSession session, ImsReasonInfo reasonInfo)1725 public void writeOnImsCallHoldFailed(int phoneId, ImsCallSession session, 1726 ImsReasonInfo reasonInfo) {} writeOnImsCallResumed(int phoneId, ImsCallSession session)1727 public void writeOnImsCallResumed(int phoneId, ImsCallSession session) {} writeOnImsCallResumeReceived(int phoneId, ImsCallSession session)1728 public void writeOnImsCallResumeReceived(int phoneId, ImsCallSession session) {} writeOnImsCallResumeFailed(int phoneId, ImsCallSession session, ImsReasonInfo reasonInfo)1729 public void writeOnImsCallResumeFailed(int phoneId, ImsCallSession session, 1730 ImsReasonInfo reasonInfo) {} writeOnRilTimeoutResponse(int phoneId, int rilSerial, int rilRequest)1731 public void writeOnRilTimeoutResponse(int phoneId, int rilSerial, int rilRequest) {} 1732 } 1733