/* Ċ Ġ* Ġ( c ) ĠCopyright ĠIBM ĠCorp . Ġ 2 0 2 1 Ċ Ġ* Ġ( c ) ĠCopyright ĠInst ana ĠInc . Ġand Ġcontributors Ġ 2 0 2 1 Ċ Ġ*/ Ċ Ċ package Ġcom . inst ana . android . core Ċ Ċ import Ġandroid . content . Context Ċ import Ġandroidx . annotation . Restrict To Ċ import Ġandroidx . annotation . Visible ForTesting Ċ import Ġandroidx . work .* Ċ import Ġcom . inst ana . android . Inst ana Ċ import Ġcom . inst ana . android . core . event . models . Beacon Ċ import Ġcom . inst ana . android . core . event . worker . Event Worker Ċ import Ġcom . inst ana . android . core . util . De bounc er Ċ import Ġcom . inst ana . android . core . util . Logger Ċ import Ġcom . inst ana . android . core . util . Rate Limiter Ċ import Ġcom . inst ana . android . core . util . isDirectory Empty Ċ import Ġkotlinx . coroutines . Dispatch ers Ċ import Ġkotlinx . coroutines . Global Scope Ċ import Ġkotlinx . coroutines . launch Ċ import Ġkotlinx . coroutines . with Context Ċ import Ġjava . io . File Ċ import Ġjava . io . IOException Ċ import Ġjava . util .* Ċ import Ġjava . util . concurrent . Executors Ċ import Ġjava . util . concurrent . Linked Blocking Deque Ċ import Ġjava . util . concurrent . TimeUnit Ċ Ċ @ Restrict To ( Restrict To . Scope . LIBRARY ) Ċ class ĠInst ana Work Manager ( ĊĠĠĠ Ġconfig : ĠInst ana Config , ĊĠĠĠ Ġprivate Ġval Ġcontext : ĠContext Ċ ) Ġ{ ĊĠĠĠ Ġprivate Ġval Ġbe ac ons DirectoryName Ġ= Ġ" inst ana Be ac ons " ĊĠĠĠ Ġprivate Ġval Ġflush Delay Ms Ġ= Ġ 1 0 0 0 L ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠRate - limits Ġthe Ġcreation Ġof Ġbe ac ons , Ġto Ġprotect Ġthe Ġservers Ġfrom Ġaccident al Ġover - usage ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġval Ġrate Limiter Ġ= ĠRate Limiter ( 1 2 8 , Ġ 3 2 ) ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠProt ect s ĠWork Manager Ġfrom Ġreceiving Ġtoo Ġmany Ġscheduled Ġtasks , Ġwhich Ġcan Ġgenerate ĠSql ite Ġerrors ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġval Ġflush De bounc er Ġ= ĠDe bounc er ( 2 0 0 0 ) ĊĊĠĠĠ Ġprivate Ġval Ġconstraints : ĠConstraints ĊĠĠĠ Ġprivate Ġvar Ġbe ac ons Directory : ĠFile ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġvar Ġinitial Delay Queue : ĠQueue < Beacon > Ġ= ĠLinked Blocking Deque () ĊĠĠĠ Ġprivate Ġvar Ġis Initial Delay Complete Ġ= Ġfalse ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġconstraints Ġ= Ġconfigure Work Manager ( config ) ĊĠĠĠĠĠĠĠ ĠExec utors . new Scheduled ThreadPool ( 1 ). schedule ({ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Initial Delay Complete Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Queue Items ( initial Delay Queue ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinitial Delay Queue . forEach Ġ{ Ġqueue ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget Work Manager ()?. run Ġ{ Ġflush ( get Be ac ons Directory (), Ġthis ) Ġ} ĊĠĠĠĠĠĠĠ Ġ}, Ġconfig . initial Beacon Delay Ms , ĠTimeUnit . MILLISECONDS ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġupdate Queue Items ( queue : ĠQueue < Beacon >) Ġ{ ĊĠĠĠĠĠĠĠ ĠLogger . d (" Updating Ġ${ queue . size } Ġqueue Ġitems ") ĊĠĠĠĠĠĠĠ Ġfor Ġ( item Ġin Ġqueue ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLogger . d (" Updating Ġqueue Ġitem Ġwith : Ġ` beacon Id ` Ġ${ item . get Beacon Id () }") ĊĠĠĠĠĠĠĠĠĠĠĠ ĠInst ana . user Profile . userName ?. run Ġ{ Ġitem . set UserName ( this ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠInst ana . user Profile . userId ?. run Ġ{ Ġitem . set UserId ( this ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠInst ana . user Profile . user Email ?. run Ġ{ Ġitem . setUser Email ( this ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( item . getView () Ġ== Ġnull ) ĠInst ana . first View ?. run Ġ{ Ġitem . setView ( this ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( item . getRoot ed () Ġ== Ġnull ) ĠInst ana . device Profile . root ed ?. run Ġ{ Ġitem . set Root ed ( this ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( item . get Google Play Services Missing () Ġ== Ġnull ) ĠInst ana . google Play Services Missing ?. run Ġ{ Ġitem . set Google Play Services Missing ( this ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠInst ana . meta . getAll (). forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( item . get Meta ( it . key ) Ġ== Ġnull ) Ġitem . set Meta ( it . key , Ġit . value ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġget Be ac ons Directory (): ĠFile Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġdirectory Ġ= Ġbe ac ons Directory ĊĠĠĠĠĠĠĠ Ġif Ġ( directory Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdirectory Ġ= ĠFile ( context . files Dir , Ġbe ac ons DirectoryName ). apply Ġ{ Ġmkdir s () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbe ac ons Directory Ġ= Ġdirectory ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġdirectory ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Visible ForTesting ĊĠĠĠ Ġinternal Ġfun Ġget Work Manager (): ĠWork Manager ? Ġ{ ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠWork Manager . getInstance () ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIllegalStateException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLogger . e (" Work Manager Ġhas Ġnot Ġbeen Ġproperly Ġinitialized . ĠPlease Ġcheck Ġyour Ġcode Ġand Ġyour Ġdependencies Ġfor Ġsimilar Ġissues ", Ġe ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ ĠLogger . e (" Inst ana ĠAgent Ġwill Ġnow Ġtry Ġto Ġinitialize ĠWork Manager Ġwith Ġthe Ġdefault Ġconfiguration ") ĊĠĠĠĠĠĠĠ Ġval Ġconfig Ġ= ĠConfiguration . Builder () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠ Ġreturn Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠWork Manager . initialize ( context , Ġconfig ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠWork Manager . getInstance () ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLogger . e (" Inst ana ĠAgent Ġfailed Ġto Ġinitialize ĠWork Manager . ĠBe ac ons Ġwill Ġnot Ġbe Ġsent Ġuntil Ġthe Ġissue Ġis Ġsolved ", Ġe ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠSet Ġconstraints Ġbased Ġon Ġconfiguration ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġconfigure Work Manager ( inst ana Config : ĠInst ana Config ): ĠConstraints Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġnetwork Type : ĠNetwork Type ĊĠĠĠĠĠĠĠ Ġval Ġlow Battery : ĠBoolean ĊĊĠĠĠĠĠĠĠ Ġwhen Ġ( inst ana Config . suspend Reporting ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠS uspend Reporting Type . NE VER Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnetwork Type Ġ= ĠNetwork Type . CONNECTED ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlow Battery Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠS uspend Reporting Type . LOW _ B ATTER Y Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnetwork Type Ġ= ĠNetwork Type . CONNECTED ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlow Battery Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠS uspend Reporting Type . CELL ULAR _ CONNECTION Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnetwork Type Ġ= ĠNetwork Type . UN METER ED ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlow Battery Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠS uspend Reporting Type . LOW _ B ATTER Y _ OR _ CELL ULAR _ CONNECTION Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnetwork Type Ġ= ĠNetwork Type . UN METER ED ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlow Battery Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn ĠConstraints . Builder () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Required Network Type ( network Type ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Requires Battery Not Low ( low Battery ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Requires Ch arging ( false ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠSend Ġall Ġbe ac ons Ġtogether Ġonce Ġbe acon - creation Ġstops Ġfor Ġ 1 s ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġflush ( directory : ĠFile , Ġmanager : ĠWork Manager ) Ġ{ ĊĠĠĠĠĠĠĠ ĠLogger . i (" Scheduling Ġbe ac ons Ġfor Ġflush ing ") ĊĠĠĠĠĠĠĠ Ġif Ġ( directory . isDirectory Empty ()) Ġreturn ĊĊĠĠĠĠĠĠĠ Ġflush De bounc er . enqueue Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtag Ġ= Ġdirectory . absolute Path ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmanager . enqueue Unique Work ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtag , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠExisting Work Policy . REPLACE , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠEvent Worker . create Work Request ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconstraints Ġ= Ġconstraints , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdirectory Ġ= Ġdirectory , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinitial Delay Ms Ġ= Ġflush Delay Ms , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtag Ġ= Ġtag ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġfun Ġqueue ( beacon : ĠBe acon ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbe acon Id Ġ= Ġbe acon . get Beacon Id () ĊĠĠĠĠĠĠĠ ĠLogger . d (" Queue ing Ġbe acon Ġwith : Ġ` beacon Id ` Ġ$ beacon Id ") ĊĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Initial Delay Complete . not () Ġ-> Ġinitial Delay Queue . add ( beacon ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbe acon Id . isNull Or Blank () Ġ-> ĠLogger . e (" Tri ed Ġto Ġqueue Ġbe acon Ġwith Ġno Ġbe acon Id : Ġ$ beacon ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrate Limiter . is Rate Exceeded ( 1 ) Ġ-> ĠLogger . e (" Max Ġbe acon - generation Ġrate Ġexceeded . ĠD ro pping Ġbe acon : Ġ$ beacon ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠGlobal Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwith Context ( Dispatch ers . IO ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfile Ġ= ĠFile ( get Be ac ons Directory (), Ġbe acon Id ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfile . write Text ( beacon . toString (), ĠChar sets . UTF _ 8 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġget Work Manager ()?. run Ġ{ Ġflush ( get Be ac ons Directory (), Ġthis ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLogger . e (" Failed Ġto Ġpersist Ġbe acon Ġin Ġfile - system . ĠD ro pping Ġbe acon : Ġ$ beacon ", Ġe ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ