1 /* 2 * Copyright (C) 2022 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.app.sdksandbox; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 24 import com.android.internal.annotations.VisibleForTesting; 25 26 import java.lang.annotation.Retention; 27 import java.lang.annotation.RetentionPolicy; 28 import java.util.Objects; 29 30 /** 31 * To be used to send sandbox latency information via callback 32 * 33 * @hide 34 */ 35 public final class SandboxLatencyInfo implements Parcelable { 36 @IntDef( 37 prefix = "METHOD_", 38 value = { 39 METHOD_UNSPECIFIED, 40 METHOD_LOAD_SDK, 41 METHOD_REQUEST_SURFACE_PACKAGE, 42 METHOD_GET_SANDBOXED_SDKS, 43 METHOD_SYNC_DATA_FROM_CLIENT, 44 METHOD_UNLOAD_SDK, 45 METHOD_ADD_SDK_SANDBOX_LIFECYCLE_CALLBACK, 46 METHOD_REMOVE_SDK_SANDBOX_LIFECYCLE_CALLBACK, 47 METHOD_GET_SANDBOXED_SDKS_VIA_CONTROLLER, 48 METHOD_REGISTER_APP_OWNED_SDK_SANDBOX_INTERFACE, 49 METHOD_UNREGISTER_APP_OWNED_SDK_SANDBOX_INTERFACE, 50 METHOD_GET_APP_OWNED_SDK_SANDBOX_INTERFACES, 51 METHOD_LOAD_SDK_VIA_CONTROLLER, 52 }) 53 @Retention(RetentionPolicy.SOURCE) 54 public @interface Method {} 55 56 public static final int METHOD_UNSPECIFIED = 0; 57 public static final int METHOD_LOAD_SDK = 1; 58 public static final int METHOD_REQUEST_SURFACE_PACKAGE = 3; 59 public static final int METHOD_GET_SANDBOXED_SDKS = 5; 60 public static final int METHOD_SYNC_DATA_FROM_CLIENT = 6; 61 public static final int METHOD_UNLOAD_SDK = 7; 62 public static final int METHOD_ADD_SDK_SANDBOX_LIFECYCLE_CALLBACK = 8; 63 public static final int METHOD_REMOVE_SDK_SANDBOX_LIFECYCLE_CALLBACK = 9; 64 public static final int METHOD_GET_SANDBOXED_SDKS_VIA_CONTROLLER = 10; 65 public static final int METHOD_REGISTER_APP_OWNED_SDK_SANDBOX_INTERFACE = 11; 66 public static final int METHOD_UNREGISTER_APP_OWNED_SDK_SANDBOX_INTERFACE = 12; 67 public static final int METHOD_GET_APP_OWNED_SDK_SANDBOX_INTERFACES = 13; 68 public static final int METHOD_LOAD_SDK_VIA_CONTROLLER = 14; 69 70 @IntDef( 71 prefix = "SANDBOX_STATUS_", 72 value = { 73 SANDBOX_STATUS_SUCCESS, 74 SANDBOX_STATUS_FAILED_AT_APP_TO_SYSTEM_SERVER, 75 SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_APP_TO_SANDBOX, 76 SANDBOX_STATUS_FAILED_AT_LOAD_SANDBOX, 77 SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_TO_SANDBOX, 78 SANDBOX_STATUS_FAILED_AT_SANDBOX, 79 SANDBOX_STATUS_FAILED_AT_SDK, 80 SANDBOX_STATUS_FAILED_AT_SANDBOX_TO_SYSTEM_SERVER, 81 SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_SANDBOX_TO_APP, 82 SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_TO_APP, 83 }) 84 @Retention(RetentionPolicy.SOURCE) 85 public @interface SandboxStatus {} 86 87 public static final int SANDBOX_STATUS_SUCCESS = 1; 88 public static final int SANDBOX_STATUS_FAILED_AT_APP_TO_SYSTEM_SERVER = 2; 89 public static final int SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_APP_TO_SANDBOX = 3; 90 public static final int SANDBOX_STATUS_FAILED_AT_LOAD_SANDBOX = 4; 91 public static final int SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_TO_SANDBOX = 5; 92 public static final int SANDBOX_STATUS_FAILED_AT_SANDBOX = 6; 93 public static final int SANDBOX_STATUS_FAILED_AT_SDK = 7; 94 public static final int SANDBOX_STATUS_FAILED_AT_SANDBOX_TO_SYSTEM_SERVER = 8; 95 public static final int SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_SANDBOX_TO_APP = 9; 96 public static final int SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_TO_APP = 10; 97 98 @IntDef( 99 prefix = "RESULT_CODE_", 100 value = { 101 RESULT_CODE_UNSPECIFIED, 102 RESULT_CODE_LOAD_SDK_NOT_FOUND, 103 RESULT_CODE_LOAD_SDK_ALREADY_LOADED, 104 RESULT_CODE_LOAD_SDK_SDK_DEFINED_ERROR, 105 RESULT_CODE_LOAD_SDK_SDK_SANDBOX_DISABLED, 106 RESULT_CODE_LOAD_SDK_INTERNAL_ERROR, 107 RESULT_CODE_SDK_SANDBOX_PROCESS_NOT_AVAILABLE 108 }) 109 @Retention(RetentionPolicy.SOURCE) 110 public @interface ResultCode {} 111 112 public static final int RESULT_CODE_UNSPECIFIED = 0; 113 public static final int RESULT_CODE_LOAD_SDK_NOT_FOUND = 1; 114 public static final int RESULT_CODE_LOAD_SDK_ALREADY_LOADED = 2; 115 public static final int RESULT_CODE_LOAD_SDK_SDK_DEFINED_ERROR = 3; 116 public static final int RESULT_CODE_LOAD_SDK_SDK_SANDBOX_DISABLED = 4; 117 public static final int RESULT_CODE_LOAD_SDK_INTERNAL_ERROR = 5; 118 public static final int RESULT_CODE_SDK_SANDBOX_PROCESS_NOT_AVAILABLE = 6; 119 120 private final @Method int mMethod; 121 private long mTimeAppCalledSystemServer = -1; 122 private long mTimeSystemServerReceivedCallFromApp = -1; 123 private long mTimeLoadSandboxStarted = -1; 124 private long mTimeSandboxLoaded = -1; 125 private long mTimeSystemServerCallFinished = -1; 126 private long mTimeSandboxReceivedCallFromSystemServer = -1; 127 private long mTimeSandboxCalledSdk = -1; 128 private long mTimeSdkCallCompleted = -1; 129 private long mTimeSandboxCalledSystemServer = -1; 130 private long mTimeSystemServerReceivedCallFromSandbox = -1; 131 private long mTimeSystemServerCalledApp = -1; 132 private long mTimeAppReceivedCallFromSystemServer = -1; 133 private @SandboxStatus int mSandboxStatus = SANDBOX_STATUS_SUCCESS; 134 private @ResultCode int mResultCode = RESULT_CODE_UNSPECIFIED; 135 136 public static final @NonNull Parcelable.Creator<SandboxLatencyInfo> CREATOR = 137 new Parcelable.Creator<SandboxLatencyInfo>() { 138 public SandboxLatencyInfo createFromParcel(Parcel in) { 139 return new SandboxLatencyInfo(in); 140 } 141 142 public SandboxLatencyInfo[] newArray(int size) { 143 return new SandboxLatencyInfo[size]; 144 } 145 }; 146 147 // TODO(b/297352617): add timeAppCalledSystemServer to the constructor. SandboxLatencyInfo(@ethod int method)148 public SandboxLatencyInfo(@Method int method) { 149 mMethod = method; 150 } 151 SandboxLatencyInfo()152 public SandboxLatencyInfo() { 153 mMethod = SandboxLatencyInfo.METHOD_UNSPECIFIED; 154 } 155 SandboxLatencyInfo(Parcel in)156 private SandboxLatencyInfo(Parcel in) { 157 mMethod = in.readInt(); 158 mTimeAppCalledSystemServer = in.readLong(); 159 mTimeSystemServerReceivedCallFromApp = in.readLong(); 160 mTimeLoadSandboxStarted = in.readLong(); 161 mTimeSandboxLoaded = in.readLong(); 162 mTimeSystemServerCallFinished = in.readLong(); 163 mTimeSandboxReceivedCallFromSystemServer = in.readLong(); 164 mTimeSandboxCalledSdk = in.readLong(); 165 mTimeSdkCallCompleted = in.readLong(); 166 mTimeSandboxCalledSystemServer = in.readLong(); 167 mTimeSystemServerReceivedCallFromSandbox = in.readLong(); 168 mTimeSystemServerCalledApp = in.readLong(); 169 mTimeAppReceivedCallFromSystemServer = in.readLong(); 170 mSandboxStatus = in.readInt(); 171 mResultCode = in.readInt(); 172 } 173 174 @Override equals(Object object)175 public boolean equals(Object object) { 176 if (this == object) return true; 177 if (!(object instanceof SandboxLatencyInfo)) return false; 178 SandboxLatencyInfo that = (SandboxLatencyInfo) object; 179 return mMethod == that.mMethod 180 && mTimeAppCalledSystemServer == that.mTimeAppCalledSystemServer 181 && mTimeSystemServerReceivedCallFromApp == that.mTimeSystemServerReceivedCallFromApp 182 && mTimeLoadSandboxStarted == that.mTimeLoadSandboxStarted 183 && mTimeSandboxLoaded == that.mTimeSandboxLoaded 184 && mTimeSystemServerCallFinished == that.mTimeSystemServerCallFinished 185 && mTimeSandboxReceivedCallFromSystemServer 186 == that.mTimeSandboxReceivedCallFromSystemServer 187 && mTimeSandboxCalledSdk == that.mTimeSandboxCalledSdk 188 && mTimeSdkCallCompleted == that.mTimeSdkCallCompleted 189 && mTimeSandboxCalledSystemServer == that.mTimeSandboxCalledSystemServer 190 && mTimeSystemServerReceivedCallFromSandbox 191 == that.mTimeSystemServerReceivedCallFromSandbox 192 && mTimeSystemServerCalledApp == that.mTimeSystemServerCalledApp 193 && mTimeAppReceivedCallFromSystemServer == that.mTimeAppReceivedCallFromSystemServer 194 && mSandboxStatus == that.mSandboxStatus 195 && mResultCode == that.mResultCode; 196 } 197 198 @Override hashCode()199 public int hashCode() { 200 return Objects.hash( 201 mMethod, 202 mTimeAppCalledSystemServer, 203 mTimeSystemServerReceivedCallFromApp, 204 mTimeLoadSandboxStarted, 205 mTimeSandboxLoaded, 206 mTimeSystemServerCallFinished, 207 mTimeSandboxReceivedCallFromSystemServer, 208 mTimeSandboxCalledSdk, 209 mTimeSdkCallCompleted, 210 mTimeSandboxCalledSystemServer, 211 mTimeSystemServerReceivedCallFromSandbox, 212 mTimeSystemServerCalledApp, 213 mTimeAppReceivedCallFromSystemServer, 214 mSandboxStatus, 215 mResultCode); 216 } 217 218 @Override writeToParcel(@onNull Parcel out, int flags)219 public void writeToParcel(@NonNull Parcel out, int flags) { 220 out.writeInt(mMethod); 221 out.writeLong(mTimeAppCalledSystemServer); 222 out.writeLong(mTimeSystemServerReceivedCallFromApp); 223 out.writeLong(mTimeLoadSandboxStarted); 224 out.writeLong(mTimeSandboxLoaded); 225 out.writeLong(mTimeSystemServerCallFinished); 226 out.writeLong(mTimeSandboxReceivedCallFromSystemServer); 227 out.writeLong(mTimeSandboxCalledSdk); 228 out.writeLong(mTimeSdkCallCompleted); 229 out.writeLong(mTimeSandboxCalledSystemServer); 230 out.writeLong(mTimeSystemServerReceivedCallFromSandbox); 231 out.writeLong(mTimeSystemServerCalledApp); 232 out.writeLong(mTimeAppReceivedCallFromSystemServer); 233 out.writeInt(mSandboxStatus); 234 out.writeInt(mResultCode); 235 } 236 237 @Override describeContents()238 public int describeContents() { 239 return 0; 240 } 241 getMethod()242 public @Method int getMethod() { 243 return mMethod; 244 } 245 setTimeAppCalledSystemServer(long timeAppCalledSystemServer)246 public void setTimeAppCalledSystemServer(long timeAppCalledSystemServer) { 247 mTimeAppCalledSystemServer = timeAppCalledSystemServer; 248 } 249 setTimeSystemServerReceivedCallFromApp(long timeSystemServerReceivedCallFromApp)250 public void setTimeSystemServerReceivedCallFromApp(long timeSystemServerReceivedCallFromApp) { 251 mTimeSystemServerReceivedCallFromApp = timeSystemServerReceivedCallFromApp; 252 } 253 setTimeLoadSandboxStarted(long timeLoadSandboxStarted)254 public void setTimeLoadSandboxStarted(long timeLoadSandboxStarted) { 255 mTimeLoadSandboxStarted = timeLoadSandboxStarted; 256 } 257 setTimeSandboxLoaded(long timeSandboxLoaded)258 public void setTimeSandboxLoaded(long timeSandboxLoaded) { 259 mTimeSandboxLoaded = timeSandboxLoaded; 260 } 261 getTimeSystemServerCallFinished()262 public long getTimeSystemServerCallFinished() { 263 return mTimeSystemServerCallFinished; 264 } 265 setTimeSystemServerCallFinished(long timeSystemServerCallFinished)266 public void setTimeSystemServerCallFinished(long timeSystemServerCallFinished) { 267 mTimeSystemServerCallFinished = timeSystemServerCallFinished; 268 } 269 setTimeSandboxReceivedCallFromSystemServer( long timeSandboxReceivedCallFromSystemServer)270 public void setTimeSandboxReceivedCallFromSystemServer( 271 long timeSandboxReceivedCallFromSystemServer) { 272 mTimeSandboxReceivedCallFromSystemServer = timeSandboxReceivedCallFromSystemServer; 273 } 274 setTimeSandboxCalledSdk(long timeSandboxCalledSdk)275 public void setTimeSandboxCalledSdk(long timeSandboxCalledSdk) { 276 mTimeSandboxCalledSdk = timeSandboxCalledSdk; 277 } 278 setTimeSdkCallCompleted(long timeSdkCallCompleted)279 public void setTimeSdkCallCompleted(long timeSdkCallCompleted) { 280 mTimeSdkCallCompleted = timeSdkCallCompleted; 281 } 282 getTimeSandboxCalledSystemServer()283 public long getTimeSandboxCalledSystemServer() { 284 return mTimeSandboxCalledSystemServer; 285 } 286 setTimeSandboxCalledSystemServer(long timeSandboxCalledSystemServer)287 public void setTimeSandboxCalledSystemServer(long timeSandboxCalledSystemServer) { 288 mTimeSandboxCalledSystemServer = timeSandboxCalledSystemServer; 289 } 290 setTimeSystemServerReceivedCallFromSandbox( long timeSystemServerReceivedCallFromSandbox)291 public void setTimeSystemServerReceivedCallFromSandbox( 292 long timeSystemServerReceivedCallFromSandbox) { 293 mTimeSystemServerReceivedCallFromSandbox = timeSystemServerReceivedCallFromSandbox; 294 } 295 setTimeSystemServerCalledApp(long timeSystemServerCalledApp)296 public void setTimeSystemServerCalledApp(long timeSystemServerCalledApp) { 297 mTimeSystemServerCalledApp = timeSystemServerCalledApp; 298 } 299 setTimeAppReceivedCallFromSystemServer(long timeAppReceivedCallFromSystemServer)300 public void setTimeAppReceivedCallFromSystemServer(long timeAppReceivedCallFromSystemServer) { 301 mTimeAppReceivedCallFromSystemServer = timeAppReceivedCallFromSystemServer; 302 } 303 setSandboxStatus(@andboxStatus int sandboxStatus)304 public void setSandboxStatus(@SandboxStatus int sandboxStatus) { 305 mSandboxStatus = sandboxStatus; 306 } 307 setResultCode(@esultCode int resultCode)308 public void setResultCode(@ResultCode int resultCode) { 309 mResultCode = resultCode; 310 } 311 312 /** Returns latency of the IPC call from App call to System Server. */ getAppToSystemServerLatency()313 public int getAppToSystemServerLatency() { 314 return getLatency(mTimeAppCalledSystemServer, mTimeSystemServerReceivedCallFromApp); 315 } 316 317 /** Returns latency of the System Server stage of the call that was received from App. */ getSystemServerAppToSandboxLatency()318 public int getSystemServerAppToSandboxLatency() { 319 int systemServerAppToSandboxLatency = 320 getLatency(mTimeSystemServerReceivedCallFromApp, mTimeSystemServerCallFinished); 321 int loadSandboxLatency = getLoadSandboxLatency(); 322 return loadSandboxLatency == -1 323 ? systemServerAppToSandboxLatency 324 : systemServerAppToSandboxLatency - loadSandboxLatency; 325 } 326 327 /** Returns latency of the LoadSandbox stage of the call. */ getLoadSandboxLatency()328 public int getLoadSandboxLatency() { 329 return getLatency(mTimeLoadSandboxStarted, mTimeSandboxLoaded); 330 } 331 332 /** Returns latency of the IPC call from System Server to Sandbox. */ getSystemServerToSandboxLatency()333 public int getSystemServerToSandboxLatency() { 334 return getLatency(mTimeSystemServerCallFinished, mTimeSandboxReceivedCallFromSystemServer); 335 } 336 337 /** Returns latency of the Sandbox stage of the call. */ getSandboxLatency()338 public int getSandboxLatency() { 339 int sandboxLatency = 340 getLatency( 341 mTimeSandboxReceivedCallFromSystemServer, mTimeSandboxCalledSystemServer); 342 int sdkLatency = getSdkLatency(); 343 if (sdkLatency != -1) { 344 sandboxLatency -= sdkLatency; 345 } 346 return sandboxLatency; 347 } 348 349 /** Returns latency of the SDK stage of the call. */ getSdkLatency()350 public int getSdkLatency() { 351 return getLatency(mTimeSandboxCalledSdk, mTimeSdkCallCompleted); 352 } 353 354 /** Returns latency of the Sandbox call to System Server. */ getSandboxToSystemServerLatency()355 public int getSandboxToSystemServerLatency() { 356 return getLatency(mTimeSandboxCalledSystemServer, mTimeSystemServerReceivedCallFromSandbox); 357 } 358 359 /** Returns latency of the System Server stage of the call that was received from Sandbox. */ getSystemServerSandboxToAppLatency()360 public int getSystemServerSandboxToAppLatency() { 361 return getLatency(mTimeSystemServerReceivedCallFromSandbox, mTimeSystemServerCalledApp); 362 } 363 364 /** Returns latency of the IPC call from System Server to App. */ getSystemServerToAppLatency()365 public int getSystemServerToAppLatency() { 366 return getLatency(mTimeSystemServerCalledApp, mTimeAppReceivedCallFromSystemServer); 367 } 368 369 /** 370 * Returns total latency of the API call. Call finish time is defined depending on the API 371 * called. 372 */ getTotalCallLatency()373 public int getTotalCallLatency() { 374 return getLatency(mTimeAppCalledSystemServer, getTotalCallFinishTime()); 375 } 376 isSuccessfulAtAppToSystemServer()377 public boolean isSuccessfulAtAppToSystemServer() { 378 return mSandboxStatus != SANDBOX_STATUS_FAILED_AT_APP_TO_SYSTEM_SERVER; 379 } 380 isSuccessfulAtSystemServerAppToSandbox()381 public boolean isSuccessfulAtSystemServerAppToSandbox() { 382 return mSandboxStatus != SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_APP_TO_SANDBOX; 383 } 384 isSuccessfulAtLoadSandbox()385 public boolean isSuccessfulAtLoadSandbox() { 386 return mSandboxStatus != SANDBOX_STATUS_FAILED_AT_LOAD_SANDBOX; 387 } 388 isSuccessfulAtSystemServerToSandbox()389 public boolean isSuccessfulAtSystemServerToSandbox() { 390 return mSandboxStatus != SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_TO_SANDBOX; 391 } 392 isSuccessfulAtSdk()393 public boolean isSuccessfulAtSdk() { 394 return mSandboxStatus != SANDBOX_STATUS_FAILED_AT_SDK; 395 } 396 isSuccessfulAtSandbox()397 public boolean isSuccessfulAtSandbox() { 398 return mSandboxStatus != SANDBOX_STATUS_FAILED_AT_SANDBOX; 399 } 400 isSuccessfulAtSandboxToSystemServer()401 public boolean isSuccessfulAtSandboxToSystemServer() { 402 return mSandboxStatus != SANDBOX_STATUS_FAILED_AT_SANDBOX_TO_SYSTEM_SERVER; 403 } 404 isSuccessfulAtSystemServerSandboxToApp()405 public boolean isSuccessfulAtSystemServerSandboxToApp() { 406 return mSandboxStatus != SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_SANDBOX_TO_APP; 407 } 408 isSuccessfulAtSystemServerToApp()409 public boolean isSuccessfulAtSystemServerToApp() { 410 return mSandboxStatus != SANDBOX_STATUS_FAILED_AT_SYSTEM_SERVER_TO_APP; 411 } 412 isTotalCallSuccessful()413 public boolean isTotalCallSuccessful() { 414 return mSandboxStatus == SANDBOX_STATUS_SUCCESS; 415 } 416 getResultCode()417 public @ResultCode int getResultCode() { 418 return mResultCode; 419 } 420 421 @VisibleForTesting getTimeAppCalledSystemServer()422 public long getTimeAppCalledSystemServer() { 423 return mTimeAppCalledSystemServer; 424 } 425 426 @VisibleForTesting getTimeAppReceivedCallFromSystemServer()427 public long getTimeAppReceivedCallFromSystemServer() { 428 return mTimeAppReceivedCallFromSystemServer; 429 } 430 getTotalCallFinishTime()431 private long getTotalCallFinishTime() { 432 switch (mMethod) { 433 case METHOD_LOAD_SDK: 434 case METHOD_LOAD_SDK_VIA_CONTROLLER: 435 case METHOD_REQUEST_SURFACE_PACKAGE: 436 return mTimeAppReceivedCallFromSystemServer; 437 case METHOD_GET_SANDBOXED_SDKS: 438 case METHOD_GET_SANDBOXED_SDKS_VIA_CONTROLLER: 439 case METHOD_REGISTER_APP_OWNED_SDK_SANDBOX_INTERFACE: 440 case METHOD_UNREGISTER_APP_OWNED_SDK_SANDBOX_INTERFACE: 441 case METHOD_GET_APP_OWNED_SDK_SANDBOX_INTERFACES: 442 case METHOD_ADD_SDK_SANDBOX_LIFECYCLE_CALLBACK: 443 case METHOD_REMOVE_SDK_SANDBOX_LIFECYCLE_CALLBACK: 444 return mTimeSystemServerCallFinished; 445 // TODO(b/243367105): change finish time for the method once latency for all stages 446 // is logged. 447 case METHOD_SYNC_DATA_FROM_CLIENT: 448 return mTimeSystemServerReceivedCallFromApp; 449 case METHOD_UNLOAD_SDK: 450 return mTimeSystemServerCalledApp; 451 default: 452 return -1; 453 } 454 } 455 getLatency(long timeEventStarted, long timeEventFinished)456 private int getLatency(long timeEventStarted, long timeEventFinished) { 457 if (timeEventStarted != -1 && timeEventFinished != -1) { 458 return ((int) (timeEventFinished - timeEventStarted)); 459 } 460 return -1; 461 } 462 } 463