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