package Ġai . fuzz yl abs . we arable my foot . imu Ċ Ċ import Ġandroid . app . Service Ċ import Ġandroid . content . Intent Ċ import Ġandroid . os . Binder Ċ import Ġandroid . os . IB inder Ċ import Ġandroid . util . Log Ċ import Ġandroid . util . Xml Ċ import Ġkotlinx . coroutines .* Ċ import Ġkotlinx . coroutines . sync . Mutex Ċ import Ġkotlinx . coroutines . sync . with Lock Ċ import Ġjava . io .* Ċ import Ġjava . time . Instant Ċ Ċ @ Experimental Unsigned Types Ċ private Ġval ĠTAG Ġ= ĠIM US ession Service :: class . java . simple Name Ċ Ċ /** Ċ Ġ* ĠService Ġthat Ġhandles Ġ[ IM US ession ] Ċ Ġ* Ċ Ġ* ĠHandles Ġsession Ġstate Ġ( connection , Ġrecording Ġand Ġsaving ) Ċ Ġ*/ Ċ @ Experimental Unsigned Types Ċ class ĠIM US ession Service Ġ: ĠService () Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġmutex Ġ= ĠMutex () ĊĊĠĠĠ Ġinner Ġclass ĠLocal Binder Ġ: ĠB inder () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġservice : ĠIM US ession Service ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġthis @ IM US ession Service ĊĠĠĠ Ġ} ĊĠĠĠ Ġprivate Ġval Ġbinder Ġ= ĠLocal Binder (); ĊĊĠĠĠ Ġprivate Ġvar Ġstate Ġ= ĠDIS CONNECTED _ STATE ĊĠĠĠ Ġprivate Ġval Ġsession Ġ= ĠIM US ession () ĊĠĠĠ Ġprivate Ġvar Ġwindow Counter Ġ= Ġ 0 ĊĠĠĠ Ġprivate Ġval Ġwindow Step Ġ= Ġ 1 0 0 ĊĠĠĠ Ġprivate Ġvar Ġvisual isation Update Counter Ġ= Ġ 0 ĊĠĠĠ Ġprivate Ġvar Ġvisual isation Update Step Ġ= Ġ 1 0 ĊĠĠĠ Ġprivate Ġvar Ġstart Timestamp : ĠInstant ? Ġ= Ġnull ĊĊĠĠĠ Ġoverride Ġfun Ġon Bind ( p 0 : ĠIntent ?): ĠI Binder ? Ġ{ ĊĠĠĠĠĠĠĠ Ġstate Ġ= ĠCONNECT ED _ STATE ĊĠĠĠĠĠĠĠ Ġreturn Ġbinder ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġvar Ġupdate Window Metrics Job : ĠJob ? Ġ= Ġnull ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠAdd Ġreading Ġto Ġ[ IM US ession ] ĊĠĠĠĠ Ġ* ĊĊĠĠĠĠ Ġ* Ġwindow , Ġand / or Ġcalculate Ġrunning Ġmetrics Ġfrom Ġthe Ġwindow ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġsuspend Ġfun Ġadd Reading ( reading : ĠI MU Reading ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( state Ġ== ĠCONNECT ED _ STATE Ġ|| Ġstate Ġ== ĠREC ORD ING _ STATE ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmutex . with Lock Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsession . shift Window ( reading , Ġstate Ġ== ĠREC ORD ING _ STATE ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwindow Counter ++ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvisual isation Update Counter ++ ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ( visual isation Update Counter Ġ>= Ġvisual isation Update Step ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmutex . with Lock Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Vis ial isation () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( window Counter Ġ>= Ġwindow Step ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif ( update Window Metrics Job ?. isActive Ġ== Ġtrue ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġ// wait Ġuntil Ġthe Ġprevious Ġjob Ġhas Ġfinished ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠPot entially ĠCPU Ġint ensive Ġtask , Ġlaunch Ġin Ġa Ġcoroutine ĊĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Window Metrics Job Ġ= ĠGlobal Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmutex . with Lock Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Window Metrics () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠStart Ġor Ġcontinue Ġsession Ġrecording ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġrecord () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( start Timestamp Ġ== Ġnull ) Ġstart Timestamp Ġ= ĠInstant . now () ĊĠĠĠĠĠĠĠ Ġstate Ġ= ĠREC ORD ING _ STATE ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠPause Ġsession Ġrecording ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġpause Recording () Ġ{ ĊĠĠĠĠĠĠĠ Ġstate Ġ= ĠCONNECT ED _ STATE ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠStop Ġrecording Ġand Ġsave Ġresults ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġstop Recording () Ġ{ ĊĠĠĠĠĠĠĠ Ġexport Session () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠExport Ġsession Ġto ĠCSV Ġand ĠGP X ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġexport Session () Ġ{ ĊĠĠĠĠĠĠĠ ĠGlobal Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠEX PORT ING _ STATE ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave To CSV () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsave To GP X () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreset () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġintent Ġ= ĠIntent ( SA VED _ ACTION ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsend Broadcast ( intent ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠCONNECT ED _ STATE ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠReset Ġthe Ġcurrent Ġ[ IM US ession ] ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġreset () Ġ{ ĊĠĠĠĠĠĠĠ Ġstart Timestamp Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġsession . clear () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠGet Ġcurrent Ġvalue Ġof Ġcad ence ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ return ĠReturns Ġthe Ġlast Ġcalculated Ġcad ence Ġestimate Ġ( or Ġ 0 . 0 , Ġif Ġnone Ġis Ġrecorded ) ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun ĠgetCurrent Cad ence (): ĠDouble Ġ= Ġsession . current Element . cad ence ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠGet Ġcurrent Ġspeed Ġin Ġk mh ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun ĠgetCurrent Speed (): ĠDouble Ġ= Ġsession . current Element . speed Ġ* ĠM PS _ TO _ K MP H ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠGet Ġcurrent Ġdistance Ġrun Ġin Ġmeters ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun ĠgetCurrent Distance (): ĠDouble Ġ= Ġsession . current Element . distance ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Window Metrics () Ġ{ ĊĠĠĠĠĠĠĠ Ġsession . update Window Metrics ( window Counter , Ġstate Ġ== ĠREC ORD ING _ STATE ) ĊĊĠĠĠĠĠĠĠ Ġval Ġintent Ġ= ĠIntent ( METR ICS _ UPDATED _ ACTION ) ĊĠĠĠĠĠĠĠ Ġintent . putExtra ( CAD ENCE _ DOUBLE , ĠgetCurrent Cad ence ()) ĊĠĠĠĠĠĠĠ Ġintent . putExtra ( SPEED _ DOUBLE , ĠgetCurrent Speed ()) ĊĠĠĠĠĠĠĠ Ġintent . putExtra ( DISTANCE _ DOUBLE , ĠgetCurrent Distance ()) ĊĠĠĠĠĠĠĠ Ġsend Broadcast ( intent ) ĊĊĠĠĠĠĠĠĠ Ġwindow Counter Ġ= Ġ 0 ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsave To CSV () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġfilename Ġ= Ġ"$ start Timestamp . csv " ĊĠĠĠĠĠĠĠ Ġval Ġpath : ĠFile ? Ġ= Ġapplication Context . get External Files Dir ( null ) ĊĠĠĠĠĠĠĠ Ġval Ġfile Ġ= ĠFile ( path , Ġfilename ) ĊĊĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġos : ĠOutputStream Ġ= ĠFileOutputStream ( file ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġos . writer (). use Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . write (" time , a X , a Y , a Z , g X , gY , g Z , pc 0 , pc 1 , pc 2 \ n ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsession . read ings . forEach Ġ{ Ġreading Ġ-> Ġit . write ( reading . to CSV Row ()) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġos . close () ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠUnable Ġto Ġcreate Ġfile , Ġlikely Ġbecause Ġexternal Ġstorage Ġis ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġnot Ġcurrently Ġmounted . ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . w ( TAG , Ġ" Error Ġwriting Ġ$ file ", Ġe ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġfile . toString ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsave To GP X () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġfilename Ġ= Ġ"$ start Timestamp . g px " ĊĠĠĠĠĠĠĠ Ġval Ġpath : ĠFile ? Ġ= Ġapplication Context . get External Files Dir ( null ) ĊĠĠĠĠĠĠĠ Ġval Ġfile Ġ= ĠFile ( path , Ġfilename ) Ċ Ċ // ĠĠĠĠĠĠĠ Ġstart Timestamp ?. let Ġ{ Ġsession . re calculate Elements ( it ) Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġelements Ġ= Ġsession . elements ĊĊĠĠĠĠĠĠĠ Ġval Ġg px Ġ= ĠXml . new Serializer () ĊĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġos : ĠOutputStream Ġ= ĠFileOutputStream ( file ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġos . writer (). use Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġg px . setOutput ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġg px . start Document (" UTF - 8 ", Ġtrue ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġg px . set Prefix ("", Ġ" http :// www . topo graf ix . com / GP X / 1 / 1 ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġg px . set Prefix (" g px tp x "," http :// www . gar min . com / xml schemas / Track Point Extension / v 1 ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġg px . set Prefix (" xsi ", Ġ" http :// www . w 3 . org / 2 0 0 1 / XMLSchema - instance ") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġg px . start Tag (" http :// www . topo graf ix . com / GP X / 1 / 1 ", Ġ" g px ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġg px . attribute (" http :// www . w 3 . org / 2 0 0 1 / XMLSchema - instance ", Ġ" schema Location ", Ġ" http :// www . topo graf ix . com / GP X / 1 / 1 Ġhttp :// www . topo graf ix . com / GP X / 1 / 1 / g px . xsd ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġg px . attribute ( null , Ġ" version ", Ġ" 1 . 1 ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġg px . attribute ( null , Ġ" creator ", Ġ" W ear able My Foot ") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġg px . start Tag ( null , Ġ" trk ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġg px . start Tag ( null , Ġ" trk seg ") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelements . forEach Ġ{ Ġelement Ġ-> Ġelement . fill GP X ( g px ) Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġg px . end Tag ( null , Ġ" trk seg ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġg px . end Tag ( null , Ġ" trk ") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġg px . end Tag (" http :// www . topo graf ix . com / GP X / 1 / 1 ", Ġ" g px ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġg px . end Document () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġg px . flush () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġos . close () ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠUnable Ġto Ġcreate Ġfile , Ġlikely Ġbecause Ġexternal Ġstorage Ġis ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġnot Ġcurrently Ġmounted . ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . w ( TAG , Ġ" Error Ġwriting Ġ$ file ", Ġe ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġfile . toString ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Vis ial isation () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġintent Ġ= ĠIntent ( VIS UAL IS ATION _ UPDATED _ ACTION ) ĊĠĠĠĠĠĠĠ Ġintent . putExtra ( VIS UAL IS ATION _ BYTE ARRAY , Ġget Bytes ()) ĊĠĠĠĠĠĠĠ Ġsend Broadcast ( intent ) ĊĠĠĠĠĠĠĠ Ġvisual isation Update Counter Ġ= Ġ 0 ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠGet Ġbytes Ġfor Ġvisual isation ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ return Ġbyte Ġarray Ġrepresentation Ġof Ġthe Ġcurrent Ġwindow ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġget Bytes (): ĠByteArray Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġsession . get Visual isation Bytes () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ@ property [ DIS CONNECTED _ STATE ] ĠService Ġis Ġdisconnected ĊĠĠĠĠ Ġ* Ġ@ property [ CONNECTED _ STATE ] ĠServices Ġis Ġconnected ĊĠĠĠĠ Ġ* Ġ@ property [ EXPORT ING _ STATE ] ĠThe Ġcurrent Ġsession Ġis Ġbeing Ġexported ĊĠĠĠĠ Ġ* Ġ@ property [ RECORD ING _ STATE ] ĠThe Ġcurrent Ġsession Ġis Ġbeing Ġrecorded ĊĠĠĠĠ Ġ* Ġ@ property [ METR ICS _ UPDATED _ ACTION ] ĠMetrics Ġupdate Ġis Ġavailable ĊĠĠĠĠ Ġ* Ġ@ property [ VIS UAL IS ATION _ UPDATED _ ACTION ] ĠByteArray Ġfor Ġvisual isation Ġis Ġupdated ĊĠĠĠĠ Ġ* Ġ@ property [ SA VED _ ACTION ] ĠA Ġsession Ġhas Ġbeen Ġsaved ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠM PS _ TO _ K MP H Ġ= Ġ 3 . 6 ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠDIS CONNECTED _ STATE Ġ= Ġ" ai . fuzz yl abs . in sole android . imu . DIS CONNECTED _ STATE " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠCONNECT ED _ STATE Ġ= Ġ" ai . fuzz yl abs . in sole android . imu . CONNECTED _ STATE " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠEX PORT ING _ STATE Ġ= Ġ" ai . fuzz yl abs . in sole android . imu . EXPORT ING _ STATE " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠREC ORD ING _ STATE Ġ= Ġ" ai . fuzz yl abs . in sole android . imu . RECORD ING _ STATE " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠMET R ICS _ UPDATED _ ACTION Ġ= Ġ" ai . fuzz yl abs . in sole andro ud . imu . METR ICS _ UPDATED _ ACTION " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠVIS UAL IS ATION _ UPDATED _ ACTION Ġ= Ġ" ai . fuzz yl abs . in sole android . imu . VIS UAL IS ATION _ UPDATED _ ACTION " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠS AV ED _ ACTION Ġ= Ġ" ai . fuzz yl abs . in sole andro ud . imu . SA VED _ ACTION " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠVIS UAL IS ATION _ BYTE ARRAY Ġ= Ġ" ai . fuzz yl abs . in sole andro ud . imu . VIS UAL IS ATION _ BYTE ARRAY " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠDEBUG _ ACTION Ġ= Ġ" ai . fuzz yl abs . in sole andro ud . imu . DEBUG _ ACTION " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠDEBUG _ STRING Ġ= Ġ" ai . fuzz yl abs . in sole andro ud . imu . DEBUG _ STRING " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠC AD ENCE _ DOUBLE Ġ= Ġ" ai . fuzz yl abs . in sole andro ud . imu . CAD ENCE _ DOUBLE " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠSPE ED _ DOUBLE Ġ= Ġ" ai . fuzz yl abs . in sole andro ud . imu . SPEED _ DOUBLE " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠDIST ANCE _ DOUBLE Ġ= Ġ" ai . fuzz yl abs . in sole andro ud . imu . DISTANCE _ DOUBLE " ĊĠĠĠ Ġ} Ċ }