package Ġcom . dew . ai h ua . download . background Ċ Ċ import Ġandroid . os . Handler Ċ import Ġandroid . os . Looper Ċ import Ġandroid . util . Log Ċ import Ġcom . dew . ai h ua . database . download DB . Mission Entity Ċ import Ġcom . dew . ai h ua . util . Utility Ċ import Ġjava . io . File Ċ import Ġjava . io . Serializable Ċ import Ġjava . lang . ref . Weak Reference Ċ import Ġjava . util . ArrayList Ċ import Ġjava . util . HashMap Ċ Ċ /** Ċ Ġ* Ġ ĠCreated Ġby ĠEd ward Ġon Ġ 3 / 2 / 2 0 1 9 . Ċ Ġ*/ Ċ class ĠMis sion Control ( val Ġmission : ĠMis sion Entity ) Ġ: ĠSerializable Ġ{ ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠNumber Ġof Ġblocks Ġwith Ġthe Ġsize Ġof Ġ[ Download Mission Manager . BLOCK _ SIZE ] ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġvar Ġblocks : ĠLong Ġ= Ġ 0 ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠNumber Ġof Ġbytes ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġvar Ġlength : ĠLong Ġ= Ġ 0 ĊĊĠĠĠ Ġvar Ġthread Count Ġ= ĠTHREAD _ COUNT ĊĠĠĠ Ġprivate Ġvar Ġfinish Count : ĠInt Ġ= Ġ 0 ĊĠĠĠ Ġ// Ġstore Ġthe Ġstate Ġof Ġblock : Ġreserved Ġor Ġnot ĊĠĠĠ Ġprivate Ġval Ġblock State : ĠMutable Map < Long , ĠBoolean > Ġ= ĠHashMap () ĊĠĠĠ Ġ// Ġstore Ġthe Ġblock Ġposition Ġof Ġa Ġbeing Ġdownloaded Ġfile Ġof Ġa Ġthread ĊĠĠĠ Ġprivate Ġval Ġthread Positions Ġ= ĠArrayList < Long >() ĊĠĠĠ Ġvar Ġrunning : ĠBoolean Ġ= Ġfalse ĊĠĠĠ Ġvar Ġfinished : ĠBoolean Ġ= Ġfalse ĊĠĠĠ Ġvar Ġfallback : ĠBoolean Ġ= Ġfalse ĊĠĠĠ Ġvar Ġerr Code Ġ= ĠNO _ ERROR ĊĊĠĠĠ Ġ@ Transient ĊĠĠĠ Ġvar Ġre covered : ĠBoolean Ġ= Ġfalse ĊĠĠĠ Ġ@ Transient ĊĠĠĠ Ġprivate Ġvar Ġm Listeners Ġ= ĠArrayList < Weak Reference < Mission Control Listener >>() ĊĠĠĠ Ġ@ Transient ĊĠĠĠ Ġprivate Ġvar Ġm Writing ToFile : ĠBoolean Ġ= Ġfalse ĊĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠGet Ġthe Ġpath Ġof Ġthe Ġmeta Ġfile ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ return Ġthe Ġpath Ġto Ġthe Ġmeta Ġfile ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġval Ġmeta Filename : ĠString ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġ"${ mission . location }/${ mission . name }. g iga " ĊĊĠĠĠ Ġval Ġdownloaded File : ĠFile ĊĠĠĠĠĠĠĠ Ġget () Ġ= ĠFile ( mission . location , Ġmission . name ) ĊĊĠĠĠ Ġprivate Ġfun Ġcheck Block ( block : ĠLong ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( block Ġ< Ġ 0 Ġ|| Ġblock Ġ>= Ġblocks ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalArgumentException (" il legal Ġblock Ġidentifier ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCheck Ġif Ġa Ġblock Ġis Ġreserved ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġblock Ġthe Ġblock Ġidentifier ĊĠĠĠĠ Ġ* Ġ@ return Ġtrue Ġif Ġthe Ġblock Ġis Ġreserved Ġand Ġfalse Ġif Ġotherwise ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġis Block Pre served ( block : ĠLong ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġcheck Block ( block ) ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( block State . containsKey ( block ) Ġ&& Ġblock State [ block ] Ġ!= Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġblock State [ block ] !! ĊĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfalse ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġset Ġblock State [ block ] Ġto Ġtrue ĊĠĠĠĠ Ġ* Ġ@ param Ġblock Ġthe Ġblock Ġid ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġpreserve Block ( block : ĠLong ) Ġ{ ĊĠĠĠĠĠĠĠ Ġcheck Block ( block ) ĊĠĠĠĠĠĠĠ Ġsynchronized ( block State ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġblock State [ block ] Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" block State : Ġ$ block State ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠSet Ġthe Ġdownload Ġposition Ġof Ġthe Ġfile ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġthread Id Ġthe Ġidentifier Ġof Ġthe Ġthread ĊĠĠĠĠ Ġ* Ġ@ param Ġposition Ġthe Ġdownload Ġposition Ġof Ġthe Ġthread Ġ( i . e Ġ: Ġ 0 Ġ- Ġthe Ġfirst Ġthread , Ġ 1 Ġ- Ġthe Ġsecond Ġthread , Ġ 2 Ġ- Ġthe Ġthird Ġthread . Ġ...) ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġset Position ( thread Id : ĠInt , Ġposition : ĠLong ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthread Positions [ thread Id ] Ġ= Ġposition ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" thread Positions Ġ= Ġ$ thread Positions ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠGet Ġthe Ġposition Ġof Ġa Ġthread ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġthread Id Ġthe Ġidentifier Ġof Ġthe Ġthread ĊĠĠĠĠ Ġ* Ġ@ return Ġthe Ġposition Ġfor Ġthe Ġthread ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġget Position ( thread Id : ĠInt ): ĠLong Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġthread Positions [ thread Id ] ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġfun Ġnotify Progress ( delta Len : ĠLong ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! running ) Ġreturn ĊĊĠĠĠĠĠĠĠ Ġif Ġ( re covered ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġre covered Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġmission . done Ġ+= Ġdelta Len ĊĊĠĠĠĠĠĠĠ Ġif Ġ( mission . done Ġ> Ġlength ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmission . done Ġ= Ġlength ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( mission . done Ġ!= Ġlength ) Ġ{ Ġ// Ġmeans Ġdownloading Ġisn 't Ġfinished Ġyet ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite This ToFile () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( ref Ġin Ġm Listeners ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlistener Ġ= Ġref . get () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( listener Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" mission . done Ġ= Ġ${ mission . done }, Ġlength Ġ= Ġ$ length Ġon ĠThread Ġname : Ġ${ Thread . currentThread (). name }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠMis sion Control Listener . handler Store [ listener ] !!. post Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlistener . on Progress Update ( this @ Mission Control , Ġmission . done , Ġlength ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCalled Ġby Ġa Ġdownload Ġthread Ġwhen Ġit Ġfinished . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġfun Ġnotify Finished () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( err Code Ġ> Ġ 0 ) Ġreturn ĊĊĠĠĠĠĠĠĠ Ġfinish Count ++ ĊĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" finish Count : Ġ$ finish Count Ġ-- Ġthread Count : Ġ$ thread Count ") ĊĠĠĠĠĠĠĠ Ġif Ġ( finish Count Ġ== Ġthread Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġon Finish () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCalled Ġwhen Ġall Ġparts Ġare Ġdownloaded ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġon Finish () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( err Code Ġ> Ġ 0 ) Ġreturn ĊĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" on Finish (): ĠDownloading Ġjust Ġfinished .") ĊĊĠĠĠĠĠĠĠ Ġrunning Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġfinished Ġ= Ġtrue ĊĊĠĠĠĠĠĠĠ Ġdelete This FromFile () ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( ref Ġin Ġm Listeners ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlistener Ġ= Ġref . get () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( listener Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠMis sion Control Listener . handler Store [ listener ] !!. post Ġ{ Ġlistener . on Finish ( this @ Mission Control ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġfun Ġnotify Error ( err : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġerr Code Ġ= Ġerr ĊĊĠĠĠĠĠĠĠ Ġwrite This ToFile () ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( ref Ġin Ġm Listeners ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlistener Ġ= Ġref . get () ĊĠĠĠĠĠĠĠĠĠĠĠ ĠMis sion Control Listener . handler Store [ listener ] !!. post Ġ{ Ġlistener !!. onError ( this @ Mission Control , Ġerr Code ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġfun Ġadd Listener ( listener : ĠMis sion Control Listener ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġhandler Ġ= ĠHandler ( Looper . get Main Looper ()) ĊĠĠĠĠĠĠĠ ĠMis sion Control Listener . handler Store [ listener ] Ġ= Ġhandler ĊĠĠĠĠĠĠĠ Ġm Listeners . add ( Weak Reference ( listener )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġfun Ġremove Listener ( listener : ĠMis sion Control Listener ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġiterator Ġ= Ġm Listeners . iterator () ĊĠĠĠĠĠĠĠ Ġwhile Ġ( iterator . hasNext ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġweak Ref Ġ= Ġiterator . next () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( listener Ġ!= Ġnull Ġ&& Ġlistener Ġ=== Ġweak Ref . get ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġiterator . remove () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠStart Ġdownloading Ġwith Ġmultiple Ġthreads . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġstart () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! running Ġ&& Ġ! finished ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrunning Ġ= Ġtrue ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! fallback ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġthread Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( thread Positions . size Ġ<= Ġi Ġ&& Ġ! re covered ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġinitialize Ġthread Positions ĠArrayList Ġbecause ĠDownload Run Ġneed Ġit Ġwith Ġvalues ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthread Positions . add ( i . to Long ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠThread ( Download Runnable ( this , Ġi )). start () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIn Ġfallback Ġmode , Ġres uming Ġis Ġnot Ġsupported . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġrestart Ġthe Ġdownloading Ġon Ġa Ġsingle Ġthread ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthread Count Ġ= Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmission . done Ġ= Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġblocks Ġ= Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠThread ( Download Runnable Fallback ( this )). start () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġpause () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( running ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrunning Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġre covered Ġ= Ġtrue ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO : ĠNotify Ġ& ĠWrite Ġstate Ġto Ġinfo Ġfile ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġif Ġ( err ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠRemoves Ġthe Ġfile Ġand Ġthe Ġmeta Ġfile ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġdelete () Ġ{ ĊĠĠĠĠĠĠĠ Ġdelete This FromFile () ĊĠĠĠĠĠĠĠ ĠFile ( mission . location , Ġmission . name ). delete () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWrite Ġthis Ġ[ Mission Control ] Ġto Ġthe Ġmeta Ġfile Ġasynchronously ĊĠĠĠĠ Ġ* Ġif Ġno Ġthread Ġis Ġalready Ġrunning . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġwrite This ToFile () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! m Writing ToFile ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġm Writing ToFile Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ ĠThread ( Runnable Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsynchronized ( block State ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠUtility . write ToFile ( meta Filename , Ġthis ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm Writing ToFile Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}). start () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġdelete This FromFile () Ġ{ ĊĠĠĠĠĠĠĠ ĠFile ( meta Filename ). delete () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠserialVersionUID Ġ= Ġ 0 L ĊĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠTAG Ġ= ĠMis sion Control :: class . java . simple Name ĊĊĠĠĠĠĠĠĠ Ġconst Ġval ĠERROR _ SERVER _ UNSUPPORTED Ġ= Ġ 2 0 6 ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠERROR _ UNKNOWN Ġ= Ġ 2 3 3 ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠNO _ ERROR Ġ= Ġ- 1 ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠTHREAD _ COUNT Ġ= Ġ 3 ĊĠĠĠ Ġ} Ċ Ċ } Ċ