package Ġde . r ki . cor on aw arn app . dat ad on ation . analytics Ċ Ċ import Ġandroidx . annotation . Visible ForTesting Ċ import Ġde . r ki . cor on aw arn app . app config . Analytics Config Ċ import Ġde . r ki . cor on aw arn app . app config . AppConfig Provider Ċ import Ġde . r ki . cor on aw arn app . app config . Config Data Ċ import Ġde . r ki . cor on aw arn app . bug reporting . report Problem Ċ import Ġde . r ki . cor on aw arn app . dat ad on ation . analytics . modules . Don or Module Ċ import Ġde . r ki . cor on aw arn app . dat ad on ation . analytics . server . Data Don ation Analytics Server Ċ import Ġde . r ki . cor on aw arn app . dat ad on ation . analytics . storage . Analytics Settings Ċ import Ġde . r ki . cor on aw arn app . dat ad on ation . analytics . storage . Last Analytics Submission Logger Ċ import Ġde . r ki . cor on aw arn app . dat ad on ation . saf et yn et . Device At testation Ċ import Ġde . r ki . cor on aw arn app . dat ad on ation . saf et yn et . Safety Net Exception Ċ import Ġde . r ki . cor on aw arn app . server . protocols . internal . pp dd . P pa Data Ċ import Ġde . r ki . cor on aw arn app . server . protocols . internal . pp dd . P pa Data Request Android Ċ import Ġde . r ki . cor on aw arn app . storage . On boarding Settings Ċ import Ġde . r ki . cor on aw arn app . util . TimeStamp er Ċ import Ġkotlinx . coroutines . Timeout Cancellation Exception Ċ import Ġkotlinx . coroutines . flow . Flow Ċ import Ġkotlinx . coroutines . sync . Mutex Ċ import Ġkotlinx . coroutines . sync . with Lock Ċ import Ġkotlinx . coroutines . with Timeout Ċ import Ġorg . joda . time . Hours Ċ import Ġtim ber . log . Tim ber Ċ import Ġjavax . inject . Inject Ċ import Ġjavax . inject . Singleton Ċ import Ġkotlin . random . Random Ċ Ċ @ Singleton Ċ class ĠAnalytics Ġ@ Inject Ġconstructor ( ĊĠĠĠ Ġprivate Ġval Ġdata Don ation Analytics Server : ĠData Don ation Analytics Server , ĊĠĠĠ Ġprivate Ġval Ġapp Config Provider : ĠApp Config Provider , ĊĠĠĠ Ġprivate Ġval Ġdevice At testation : ĠDevice At testation , ĊĠĠĠ Ġ// Ġ@ Jvm Suppress W ild cards Ġis Ġneeded Ġfor Ġ@ Into Set Ġinjection Ġin ĠKotlin ĊĠĠĠ Ġprivate Ġval Ġdon or Modules : ĠSet < @ Jvm Suppress W ild cards ĠDon or Module >, ĊĠĠĠ Ġprivate Ġval Ġsettings : ĠAnalytics Settings , ĊĠĠĠ Ġprivate Ġval Ġlogger : ĠLast Analytics Submission Logger , ĊĠĠĠ Ġprivate Ġval Ġtime Stamp er : ĠTime Stamp er , ĊĠĠĠ Ġprivate Ġval Ġon boarding Settings : ĠOn boarding Settings Ċ ) Ġ{ ĊĠĠĠ Ġprivate Ġval Ġsubmission Lock out Mutex Ġ= ĠMutex () ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġtry Submission ( analytics Config : ĠAnalytics Config , Ġp pa Data : ĠP pa Data . PP A Data Android ): ĠResult Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġp pa At testation Request Ġ= ĠP PA Device At testation Request ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġp pa Data Ġ= Ġp pa Data ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . tag ( TAG ). d (" Starting Ġsafety Ġnet Ġdevice Ġat testation ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġat testation Ġ= Ġdevice At testation . at test ( pp a At testation Request ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġat testation . require Pass ( analytics Config . safety Net Requirements ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . tag ( TAG ). d (" Safety Ġnet Ġat testation Ġpassed ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġp pa Container Ġ= ĠP pa Data Request Android . PP A Data Request Android . newBuilder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Authentication ( at testation . access Control Proto Buf ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Payload ( pp a Data ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . tag ( TAG ). d (" Starting Ġanalytics Ġupload ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġdata Don ation Analytics Server . upload Analytics Data ( pp a Container ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . tag ( TAG ). d (" Analytics Ġupload Ġfinished ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠResult ( successful Ġ= Ġtrue ) ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( err : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġerr . report Problem ( tag Ġ= ĠTAG , Ġinfo Ġ= Ġ" An Ġerror Ġoccurred Ġduring Ġanalytics Ġsubmission ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġretry Ġ= Ġerr Ġis ĠS afety Net Exception Ġ&& Ġerr . type Ġ== ĠS afety Net Exception . Type . AT TEST ATION _ REQUEST _ FAILED ĊĠĠĠĠĠĠĠĠĠĠĠ ĠResult ( successful Ġ= Ġfalse , Ġshould Retry Ġ= Ġretry ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġsuspend Ġfun Ġcollect Cont ributions ( ĊĠĠĠĠĠĠĠ Ġconfig Data : ĠConfig Data , ĊĠĠĠĠĠĠĠ Ġp pa Data Builder : ĠP pa Data . PP A Data Android . Builder ĊĠĠĠ Ġ): ĠList < Don or Module . Contribution > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġrequest : ĠDon or Module . Request Ġ= Ġobject Ġ: ĠDon or Module . Request Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġval Ġcurrent Config : ĠConfig Data Ġ= Ġconfig Data ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġcontributions Ġ= Ġdon or Modules . map NotNull Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠmoduleName Ġ= Ġit :: class . simple Name ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . tag ( TAG ). d (" Beginning Ġdon ation Ġfor Ġmodule : Ġ% s ", ĠmoduleName ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . begin Don ation ( request ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġe . report Problem ( TAG , Ġ" begin Don ation ($ request ): Ġ$ moduleName Ġfailed ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontributions . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠmoduleName Ġ= Ġit :: class . simple Name ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . tag ( TAG ). d (" Inject ing Ġcontribution : Ġ% s ", ĠmoduleName ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . inject Data ( pp a Data Builder ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġe . report Problem ( TAG , Ġ" inject Data ($ pp a Data Builder ): Ġ$ moduleName Ġfailed ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġcontributions ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Visible ForTesting ( otherwise Ġ= ĠVis ible ForTesting . PRIVATE ) ĊĠĠĠ Ġsuspend Ġfun Ġsubmit Analytics Data ( config Data : ĠConfig Data ): ĠResult Ġ{ ĊĠĠĠĠĠĠĠ ĠTim ber . tag ( TAG ). d (" Starting Ġanalytics Ġsubmission ") ĊĊĠĠĠĠĠĠĠ Ġval Ġp pa Data Builder Ġ= ĠP pa Data . PP A Data Android . newBuilder () ĊĊĠĠĠĠĠĠĠ Ġval Ġcontributions Ġ= Ġcollect Cont ributions ( config Data , Ġp pa Data Builder ) ĊĊĠĠĠĠĠĠĠ Ġval Ġanalytics Proto Ġ= Ġp pa Data Builder . build () ĊĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġ 6 min , Ġif Ġat testation Ġand / or Ġsubmission Ġtakes Ġlonger Ġthan Ġthat , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġthen Ġwe Ġwant Ġto Ġgive Ġmodules Ġstill Ġtime Ġto Ġcleanup Ġand Ġget Ġinto Ġa Ġconsistent Ġstate . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwith Timeout ( 3 6 0 _ 0 0 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Submission ( config Data . analytics , Ġanalytics Proto ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠTimeout Cancellation Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . tag ( TAG ). e ( e , Ġ" try Submission () Ġtimed Ġout Ġafter Ġ 3 6 0 s .") ĊĠĠĠĠĠĠĠĠĠĠĠ ĠResult ( successful Ġ= Ġfalse , Ġshould Retry Ġ= Ġtrue ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontributions . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠmoduleName Ġ= Ġit :: class . simple Name ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . tag ( TAG ). d (" Finish ing Ġcontribution ($ result ) Ġfor Ġ% s ", ĠmoduleName ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . finish Don ation ( result . successful ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġe . report Problem ( TAG , Ġ" finish Don ation ($ result ): Ġ$ moduleName Ġfailed ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( result . successful ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsettings . last Submitted Timestamp . update Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtime Stamp er . now UTC ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . store Analytics Data ( analytics Proto ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠTim ber . tag ( TAG ). d (" Finished Ġanalytics Ġsubmission Ġresult =% s ", Ġresult ) ĊĠĠĠĠĠĠĠ Ġreturn Ġresult ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Visible ForTesting ( otherwise Ġ= ĠVis ible ForTesting . PRIVATE ) ĊĠĠĠ Ġfun Ġstop Due To No Analytics Config ( analytics Config : ĠAnalytics Config ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġ! analytics Config . analytics Enabled ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Visible ForTesting ( otherwise Ġ= ĠVis ible ForTesting . PRIVATE ) ĊĠĠĠ Ġfun Ġstop Due To No User Consent (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġ! settings . analytics Enabled . value ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Visible ForTesting ( otherwise Ġ= ĠVis ible ForTesting . PRIVATE ) ĊĠĠĠ Ġfun Ġstop Due To Probability To Submit ( analytics Config : ĠAnalytics Config ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġsubmit Roll Ġ= ĠRandom . next Double ( 0 . 0 , Ġ 1 . 0 ) ĊĠĠĠĠĠĠĠ Ġreturn Ġsubmit Roll Ġ> Ġanalytics Config . probability To Submit ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Visible ForTesting ( otherwise Ġ= ĠVis ible ForTesting . PRIVATE ) ĊĠĠĠ Ġfun Ġstop Due To Last Submitted Timestamp (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġlast Submit Ġ= Ġsettings . last Submitted Timestamp . value Ġ?: Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġreturn Ġlast Submit . plus ( Hours . hours ( LAST _ SUB MISSION _ MIN _ AGE _ HOUR S ). to Standard Duration ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. is After ( time Stamp er . now UTC ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Visible ForTesting ( otherwise Ġ= ĠVis ible ForTesting . PRIVATE ) ĊĠĠĠ Ġfun Ġstop Due To Time Since On boarding (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġon boarding Ġ= Ġon boarding Settings . on boarding Completed Timestamp . value Ġ?: Ġreturn Ġtrue ĊĠĠĠĠĠĠĠ Ġreturn Ġon boarding . plus ( Hours . hours ( ON BOARD ING _ DELAY _ HOUR S ). to Standard Duration ()). is After ( time Stamp er . now UTC ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġsuspend Ġfun Ġsubmit If W anted (): ĠResult Ġ= Ġsubmission Lock out Mutex . with Lock Ġ{ ĊĠĠĠĠĠĠĠ ĠTim ber . tag ( TAG ). d (" Checking Ġanalytics Ġconditions ") ĊĠĠĠĠĠĠĠ Ġval Ġconfig Data : ĠConfig Data Ġ= Ġapp Config Provider . get AppConfig () ĊĊĠĠĠĠĠĠĠ Ġif Ġ( stop Due To No Analytics Config ( config Data . analytics )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . tag ( TAG ). w (" Abort ing ĠAnalytics Ġsubmission Ġdue Ġto Ġno Analytics Config ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ with Lock ĠResult ( successful Ġ= Ġfalse ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( stop Due To No User Consent ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . tag ( TAG ). w (" Abort ing ĠAnalytics Ġsubmission Ġdue Ġto Ġno User Consent ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ with Lock ĠResult ( successful Ġ= Ġfalse ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( stop Due To Probability To Submit ( config Data . analytics )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . tag ( TAG ). w (" Abort ing ĠAnalytics Ġsubmission Ġdue Ġto Ġprobability To Submit ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ with Lock ĠResult ( successful Ġ= Ġfalse ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( stop Due To Last Submitted Timestamp ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . tag ( TAG ). w (" Abort ing ĠAnalytics Ġsubmission Ġdue Ġto Ġlast Submitted Timestamp ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ with Lock ĠResult ( successful Ġ= Ġfalse ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( stop Due To Time Since On boarding ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . tag ( TAG ). w (" Abort ing ĠAnalytics Ġsubmission Ġdue Ġto Ġtime Since On boarding ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ with Lock ĠResult ( successful Ġ= Ġfalse ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn @ with Lock Ġsubmit Analytics Data ( config Data ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġdelete All Data () Ġ= Ġsubmission Lock out Mutex . with Lock Ġ{ ĊĠĠĠĠĠĠĠ Ġdon or Modules . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . delete Data () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġsuspend Ġfun Ġset Analytics Enabled ( enabled : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ Ġsettings . analytics Enabled . update Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġenabled ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ(! enabled ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdelete All Data () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġis Analytics Enabled Flow (): ĠFlow < Boolean > Ġ= ĊĠĠĠĠĠĠĠ Ġsettings . analytics Enabled . flow ĊĊĠĠĠ Ġdata Ġclass ĠResult ( ĊĠĠĠĠĠĠĠ Ġval Ġsuccessful : ĠBoolean , ĊĠĠĠĠĠĠĠ Ġval Ġshould Retry : ĠBoolean Ġ= Ġfalse ĊĠĠĠ Ġ) ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠTAG Ġ= ĠAnalytics :: class . java . simple Name ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠLAST _ SUB MISSION _ MIN _ AGE _ HOUR S Ġ= Ġ 2 3 ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠON BOARD ING _ DELAY _ HOUR S Ġ= Ġ 2 4 ĊĊĠĠĠĠĠĠĠ Ġdata Ġclass ĠP PA Device At testation Request ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġp pa Data : ĠP pa Data . PP A Data Android ĊĠĠĠĠĠĠĠ Ġ) Ġ: ĠDevice At testation . Request Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġval Ġscenario Payload : ĠByteArray ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġp pa Data . toByteArray () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ