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 android.telecom; 18 19 import android.annotation.SystemApi; 20 import android.os.Parcel; 21 import android.os.Parcelable; 22 23 import java.util.ArrayList; 24 import java.util.LinkedList; 25 import java.util.List; 26 27 /** 28 * @hide 29 */ 30 @SystemApi 31 public class ParcelableCallAnalytics implements Parcelable { 32 /** {@hide} */ 33 public static final class VideoEvent implements Parcelable { 34 public static final int SEND_LOCAL_SESSION_MODIFY_REQUEST = 0; 35 public static final int SEND_LOCAL_SESSION_MODIFY_RESPONSE = 1; 36 public static final int RECEIVE_REMOTE_SESSION_MODIFY_REQUEST = 2; 37 public static final int RECEIVE_REMOTE_SESSION_MODIFY_RESPONSE = 3; 38 39 public static final Parcelable.Creator<VideoEvent> CREATOR = 40 new Parcelable.Creator<VideoEvent> () { 41 42 @Override 43 public VideoEvent createFromParcel(Parcel in) { 44 return new VideoEvent(in); 45 } 46 47 @Override 48 public VideoEvent[] newArray(int size) { 49 return new VideoEvent[size]; 50 } 51 }; 52 53 private int mEventName; 54 private long mTimeSinceLastEvent; 55 private int mVideoState; 56 57 public VideoEvent(int eventName, long timeSinceLastEvent, int videoState) { 58 mEventName = eventName; 59 mTimeSinceLastEvent = timeSinceLastEvent; 60 mVideoState = videoState; 61 } 62 63 VideoEvent(Parcel in) { 64 mEventName = in.readInt(); 65 mTimeSinceLastEvent = in.readLong(); 66 mVideoState = in.readInt(); 67 } 68 69 public int getEventName() { 70 return mEventName; 71 } 72 73 public long getTimeSinceLastEvent() { 74 return mTimeSinceLastEvent; 75 } 76 77 public int getVideoState() { 78 return mVideoState; 79 } 80 81 @Override 82 public int describeContents() { 83 return 0; 84 } 85 86 @Override 87 public void writeToParcel(Parcel out, int flags) { 88 out.writeInt(mEventName); 89 out.writeLong(mTimeSinceLastEvent); 90 out.writeInt(mVideoState); 91 } 92 } 93 94 public static final class AnalyticsEvent implements Parcelable { 95 public static final int SET_SELECT_PHONE_ACCOUNT = 0; 96 public static final int SET_ACTIVE = 1; 97 public static final int SET_DISCONNECTED = 2; 98 public static final int START_CONNECTION = 3; 99 public static final int SET_DIALING = 4; 100 public static final int BIND_CS = 5; 101 public static final int CS_BOUND = 6; 102 public static final int REQUEST_ACCEPT = 7; 103 public static final int REQUEST_REJECT = 8; 104 105 public static final int SCREENING_SENT = 100; 106 public static final int SCREENING_COMPLETED = 101; 107 public static final int DIRECT_TO_VM_INITIATED = 102; 108 public static final int DIRECT_TO_VM_FINISHED = 103; 109 public static final int BLOCK_CHECK_INITIATED = 104; 110 public static final int BLOCK_CHECK_FINISHED = 105; 111 public static final int FILTERING_INITIATED = 106; 112 public static final int FILTERING_COMPLETED = 107; 113 public static final int FILTERING_TIMED_OUT = 108; 114 115 public static final int SKIP_RINGING = 200; 116 public static final int SILENCE = 201; 117 public static final int MUTE = 202; 118 public static final int UNMUTE = 203; 119 public static final int AUDIO_ROUTE_BT = 204; 120 public static final int AUDIO_ROUTE_EARPIECE = 205; 121 public static final int AUDIO_ROUTE_HEADSET = 206; 122 public static final int AUDIO_ROUTE_SPEAKER = 207; 123 124 public static final int CONFERENCE_WITH = 300; 125 public static final int SPLIT_CONFERENCE = 301; 126 public static final int SET_PARENT = 302; 127 128 public static final int REQUEST_HOLD = 400; 129 public static final int REQUEST_UNHOLD = 401; 130 public static final int REMOTELY_HELD = 402; 131 public static final int REMOTELY_UNHELD = 403; 132 public static final int SET_HOLD = 404; 133 public static final int SWAP = 405; 134 135 public static final int REQUEST_PULL = 500; 136 137 138 public static final Parcelable.Creator<AnalyticsEvent> CREATOR = 139 new Parcelable.Creator<AnalyticsEvent> () { 140 141 @Override 142 public AnalyticsEvent createFromParcel(Parcel in) { 143 return new AnalyticsEvent(in); 144 } 145 146 @Override 147 public AnalyticsEvent[] newArray(int size) { 148 return new AnalyticsEvent[size]; 149 } 150 }; 151 152 private int mEventName; 153 private long mTimeSinceLastEvent; 154 155 public AnalyticsEvent(int eventName, long timestamp) { 156 mEventName = eventName; 157 mTimeSinceLastEvent = timestamp; 158 } 159 160 AnalyticsEvent(Parcel in) { 161 mEventName = in.readInt(); 162 mTimeSinceLastEvent = in.readLong(); 163 } 164 165 public int getEventName() { 166 return mEventName; 167 } 168 169 public long getTimeSinceLastEvent() { 170 return mTimeSinceLastEvent; 171 } 172 173 @Override 174 public int describeContents() { 175 return 0; 176 } 177 178 @Override 179 public void writeToParcel(Parcel out, int flags) { 180 out.writeInt(mEventName); 181 out.writeLong(mTimeSinceLastEvent); 182 } 183 } 184 185 public static final class EventTiming implements Parcelable { 186 public static final int ACCEPT_TIMING = 0; 187 public static final int REJECT_TIMING = 1; 188 public static final int DISCONNECT_TIMING = 2; 189 public static final int HOLD_TIMING = 3; 190 public static final int UNHOLD_TIMING = 4; 191 public static final int OUTGOING_TIME_TO_DIALING_TIMING = 5; 192 public static final int BIND_CS_TIMING = 6; 193 public static final int SCREENING_COMPLETED_TIMING = 7; 194 public static final int DIRECT_TO_VM_FINISHED_TIMING = 8; 195 public static final int BLOCK_CHECK_FINISHED_TIMING = 9; 196 public static final int FILTERING_COMPLETED_TIMING = 10; 197 public static final int FILTERING_TIMED_OUT_TIMING = 11; 198 199 public static final int INVALID = 999999; 200 201 public static final Parcelable.Creator<EventTiming> CREATOR = 202 new Parcelable.Creator<EventTiming> () { 203 204 @Override 205 public EventTiming createFromParcel(Parcel in) { 206 return new EventTiming(in); 207 } 208 209 @Override 210 public EventTiming[] newArray(int size) { 211 return new EventTiming[size]; 212 } 213 }; 214 215 private int mName; 216 private long mTime; 217 218 public EventTiming(int name, long time) { 219 this.mName = name; 220 this.mTime = time; 221 } 222 223 private EventTiming(Parcel in) { 224 mName = in.readInt(); 225 mTime = in.readLong(); 226 } 227 228 public int getName() { 229 return mName; 230 } 231 232 public long getTime() { 233 return mTime; 234 } 235 236 @Override 237 public int describeContents() { 238 return 0; 239 } 240 241 @Override 242 public void writeToParcel(Parcel out, int flags) { 243 out.writeInt(mName); 244 out.writeLong(mTime); 245 } 246 } 247 248 public static final int CALLTYPE_UNKNOWN = 0; 249 public static final int CALLTYPE_INCOMING = 1; 250 public static final int CALLTYPE_OUTGOING = 2; 251 252 // Constants for call technology 253 public static final int CDMA_PHONE = 0x1; 254 public static final int GSM_PHONE = 0x2; 255 public static final int IMS_PHONE = 0x4; 256 public static final int SIP_PHONE = 0x8; 257 public static final int THIRD_PARTY_PHONE = 0x10; 258 259 public static final long MILLIS_IN_5_MINUTES = 1000 * 60 * 5; 260 public static final long MILLIS_IN_1_SECOND = 1000; 261 262 public static final int STILL_CONNECTED = -1; 263 264 public static final Parcelable.Creator<ParcelableCallAnalytics> CREATOR = 265 new Parcelable.Creator<ParcelableCallAnalytics> () { 266 267 @Override 268 public ParcelableCallAnalytics createFromParcel(Parcel in) { 269 return new ParcelableCallAnalytics(in); 270 } 271 272 @Override 273 public ParcelableCallAnalytics[] newArray(int size) { 274 return new ParcelableCallAnalytics[size]; 275 } 276 }; 277 278 // The start time of the call in milliseconds since Jan. 1, 1970, rounded to the nearest 279 // 5 minute increment. 280 private final long startTimeMillis; 281 282 // The duration of the call, in milliseconds. 283 private final long callDurationMillis; 284 285 // ONE OF calltype_unknown, calltype_incoming, or calltype_outgoing 286 private final int callType; 287 288 // true if the call came in while another call was in progress or if the user dialed this call 289 // while in the middle of another call. 290 private final boolean isAdditionalCall; 291 292 // true if the call was interrupted by an incoming or outgoing call. 293 private final boolean isInterrupted; 294 295 // bitmask denoting which technologies a call used. 296 private final int callTechnologies; 297 298 // Any of the DisconnectCause codes, or STILL_CONNECTED. 299 private final int callTerminationCode; 300 301 // Whether the call is an emergency call 302 private final boolean isEmergencyCall; 303 304 // The package name of the connection service that this call used. 305 private final String connectionService; 306 307 // Whether the call object was created from an existing connection. 308 private final boolean isCreatedFromExistingConnection; 309 310 // A list of events that are associated with this call 311 private final List<AnalyticsEvent> analyticsEvents; 312 313 // A map from event-pair names to their durations. 314 private final List<EventTiming> eventTimings; 315 316 // Whether the call has ever been a video call. 317 private boolean isVideoCall = false; 318 319 // A list of video events that have occurred. 320 private List<VideoEvent> videoEvents; 321 322 public ParcelableCallAnalytics(long startTimeMillis, long callDurationMillis, int callType, 323 boolean isAdditionalCall, boolean isInterrupted, int callTechnologies, 324 int callTerminationCode, boolean isEmergencyCall, String connectionService, 325 boolean isCreatedFromExistingConnection, List<AnalyticsEvent> analyticsEvents, 326 List<EventTiming> eventTimings) { 327 this.startTimeMillis = startTimeMillis; 328 this.callDurationMillis = callDurationMillis; 329 this.callType = callType; 330 this.isAdditionalCall = isAdditionalCall; 331 this.isInterrupted = isInterrupted; 332 this.callTechnologies = callTechnologies; 333 this.callTerminationCode = callTerminationCode; 334 this.isEmergencyCall = isEmergencyCall; 335 this.connectionService = connectionService; 336 this.isCreatedFromExistingConnection = isCreatedFromExistingConnection; 337 this.analyticsEvents = analyticsEvents; 338 this.eventTimings = eventTimings; 339 } 340 341 public ParcelableCallAnalytics(Parcel in) { 342 startTimeMillis = in.readLong(); 343 callDurationMillis = in.readLong(); 344 callType = in.readInt(); 345 isAdditionalCall = readByteAsBoolean(in); 346 isInterrupted = readByteAsBoolean(in); 347 callTechnologies = in.readInt(); 348 callTerminationCode = in.readInt(); 349 isEmergencyCall = readByteAsBoolean(in); 350 connectionService = in.readString(); 351 isCreatedFromExistingConnection = readByteAsBoolean(in); 352 analyticsEvents = new ArrayList<>(); 353 in.readTypedList(analyticsEvents, AnalyticsEvent.CREATOR); 354 eventTimings = new ArrayList<>(); 355 in.readTypedList(eventTimings, EventTiming.CREATOR); 356 isVideoCall = readByteAsBoolean(in); 357 videoEvents = new LinkedList<>(); 358 in.readTypedList(videoEvents, VideoEvent.CREATOR); 359 } 360 361 public void writeToParcel(Parcel out, int flags) { 362 out.writeLong(startTimeMillis); 363 out.writeLong(callDurationMillis); 364 out.writeInt(callType); 365 writeBooleanAsByte(out, isAdditionalCall); 366 writeBooleanAsByte(out, isInterrupted); 367 out.writeInt(callTechnologies); 368 out.writeInt(callTerminationCode); 369 writeBooleanAsByte(out, isEmergencyCall); 370 out.writeString(connectionService); 371 writeBooleanAsByte(out, isCreatedFromExistingConnection); 372 out.writeTypedList(analyticsEvents); 373 out.writeTypedList(eventTimings); 374 writeBooleanAsByte(out, isVideoCall); 375 out.writeTypedList(videoEvents); 376 } 377 378 /** {@hide} */ 379 public void setIsVideoCall(boolean isVideoCall) { 380 this.isVideoCall = isVideoCall; 381 } 382 383 /** {@hide} */ 384 public void setVideoEvents(List<VideoEvent> videoEvents) { 385 this.videoEvents = videoEvents; 386 } 387 388 public long getStartTimeMillis() { 389 return startTimeMillis; 390 } 391 392 public long getCallDurationMillis() { 393 return callDurationMillis; 394 } 395 396 public int getCallType() { 397 return callType; 398 } 399 400 public boolean isAdditionalCall() { 401 return isAdditionalCall; 402 } 403 404 public boolean isInterrupted() { 405 return isInterrupted; 406 } 407 408 public int getCallTechnologies() { 409 return callTechnologies; 410 } 411 412 public int getCallTerminationCode() { 413 return callTerminationCode; 414 } 415 416 public boolean isEmergencyCall() { 417 return isEmergencyCall; 418 } 419 420 public String getConnectionService() { 421 return connectionService; 422 } 423 424 public boolean isCreatedFromExistingConnection() { 425 return isCreatedFromExistingConnection; 426 } 427 428 public List<AnalyticsEvent> analyticsEvents() { 429 return analyticsEvents; 430 } 431 432 public List<EventTiming> getEventTimings() { 433 return eventTimings; 434 } 435 436 /** {@hide} */ 437 public boolean isVideoCall() { 438 return isVideoCall; 439 } 440 441 /** {@hide} */ 442 public List<VideoEvent> getVideoEvents() { 443 return videoEvents; 444 } 445 446 @Override 447 public int describeContents() { 448 return 0; 449 } 450 451 private static void writeBooleanAsByte(Parcel out, boolean b) { 452 out.writeByte((byte) (b ? 1 : 0)); 453 } 454 455 private static boolean readByteAsBoolean(Parcel in) { 456 return (in.readByte() == 1); 457 } 458 } 459