package Ġcom . be eper . sms Ċ Ċ import Ġandroid . content . Context Ċ import Ġandroid . os . Build Ċ import Ġcom . be eper . sms . Bridge Service . Companion . start Bridge Ċ import Ġcom . be eper . sms . Bridge Service . Companion . stop Bridge Ċ import Ġcom . be eper . sms . commands . Command Ċ import Ġcom . be eper . sms . commands . outgoing . Error Ċ import Ġcom . be eper . sms . commands . outgoing . Push Key Ċ import Ġcom . be eper . sms . extensions . cacheDir Ċ import Ġcom . be eper . sms . extensions . env Ċ import Ġcom . be eper . sms . extensions . has Permissions Ċ import Ġcom . be eper . sms . helpers . new Gson Ċ import Ġcom . google . gson . Json Element Ċ import Ġkotlinx . coroutines .* Ċ import Ġkotlinx . coroutines . flow . Mutable Shared Flow Ċ import Ġkotlinx . coroutines . flow . first Ċ import Ġkotlinx . coroutines . flow . on Subscription Ċ import Ġjava . io . File Ċ import Ġjava . io . InputStream Ċ import Ġjava . util . concurrent . Executors . new Single Thread Executor Ċ import Ġjava . util . concurrent . atomic . Atomic Integer Ċ import Ġkotlin . coroutines . suspend Coroutine Ċ Ċ class ĠBridge Ġprivate Ġconstructor () Ġ{ ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġnative Lib Dir : ĠString ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġchannel Id : ĠString ĊĠĠĠ Ġprivate Ġvar Ġconfig Path Provider : Ġ( suspend Ġ() Ġ-> ĠString ? )? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġvar Ġconfig Path : ĠString ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġvar Ġcache Dir : ĠString ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġvar Ġchannel Icon : ĠInt ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġvar Ġpush Key : ĠPush Key ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġvar Ġprocess : ĠProcess ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġval Ġoutgoing Ġ= Ġnew Single Thread Executor (). as Coroutine Dispatcher () ĊĠĠĠ Ġprivate Ġval Ġscope Ġ= ĠCor outine Scope ( Supervisor Job () Ġ+ ĠDispatch ers . IO ) ĊĠĠĠ Ġprivate Ġval Ġresponse Flow Ġ= ĠMutable Shared Flow < Pair < Int , ĠJson Element >>() ĊĠĠĠ Ġprivate Ġval ĠrequestId Ġ= ĠAtomicInteger ( 0 ) ĊĊĠĠĠ Ġfun Ġinit ( ĊĠĠĠĠĠĠĠ Ġcontext : ĠContext , ĊĠĠĠĠĠĠĠ Ġchannel Id : ĠString Ġ= ĠDEFAULT _ CHANNEL _ ID , ĊĠĠĠĠĠĠĠ Ġchannel Icon : ĠInt ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠ Ġpush Key : ĠPush Key ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠ Ġconfig Path Provider : Ġsuspend Ġ() Ġ-> ĠString ?, ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" init ") ĊĠĠĠĠĠĠĠ ĠUp grader ( context ). upgrade () ĊĠĠĠĠĠĠĠ Ġthis . config Path Provider Ġ= Ġconfig Path Provider ĊĠĠĠĠĠĠĠ Ġthis . channelId Ġ= Ġchannel Id ĊĠĠĠĠĠĠĠ Ġthis . channel Icon Ġ= Ġchannel Icon ĊĠĠĠĠĠĠĠ Ġthis . push Key Ġ= Ġpush Key ĊĠĠĠĠĠĠĠ Ġnative Lib Dir Ġ= Ġcontext . application Info . native Library Dir ĊĠĠĠĠĠĠĠ Ġcache Dir Ġ= Ġcontext . cacheDir (" ma ut rix ") ĊĠĠĠĠĠĠĠ ĠS ms Observer ( context ). register Observer () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġstart ( context : ĠContext ?) Ġ= Ġscope . launch Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" start ") ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( context ?. has Permissions Ġ== Ġtrue Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠgetConfig (). exists () Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġget Process ()?. running Ġ== Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . start Bridge ( channelId , Ġchannel Icon , Ġpush Key ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . e ( TAG , Ġe . message Ġ?: Ġ" Error ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġstop ( context : ĠContext ) Ġ= ĊĠĠĠĠĠĠĠ Ġcontext ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. stop Bridge () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. apply Ġ{ ĠLog . d ( TAG , Ġ" stop Ġsuccess =$ this ") Ġ} ĊĊĠĠĠ Ġfun Ġsign Out ( context : ĠContext ) Ġ{ ĊĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Stopping Ġbridge ") ĊĠĠĠĠĠĠĠ Ġstop ( context ) ĊĠĠĠĠĠĠĠ Ġconfig Path Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġconfig Path Provider Ġ= Ġnull ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġping () Ġ{ ĊĠĠĠĠĠĠĠ Ġsend ( Command (" ping _ server ", Ġnull )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġprivate Ġfun Ġget Process (): ĠProcess ? Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġconfig Ġ= Ġconfig Path Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġval Ġcache Ġ= Ġcache Dir Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġif Ġ( process ?. running Ġ!= Ġtrue ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Starting Ġm aut rix - ime ssage ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprocess Ġ= ĠProcess Builder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. env ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" LD _ LIBRARY _ PATH " Ġto Ġnative Lib Dir , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" TMP DIR " Ġto Ġcache , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. directory ( native Lib Dir . to File ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. command ("./ lib ma ut rix . so ", Ġ"- c ", Ġconfig ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. start () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. also Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . running ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" Started ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġprocess ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun ĠgetConfig (): ĠString ? Ġ= ĊĠĠĠĠĠĠĠ Ġconfig Path Ġ?: Ġconfig Path Provider ?. invoke ()?. take If Ġ{ Ġit . exists () Ġ} ?. also Ġ{ Ġconfig Path Ġ= Ġit Ġ} ĊĊĠĠĠ Ġfun Ġkill Process () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( Build . VERSION . SDK _ INT Ġ>= ĠBuild . VERSION _ CODES . O ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprocess ?. destroy For c ibly () ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprocess ?. destroy () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġprocess Ġ= Ġnull ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinternal Ġfun ĠforEach Error ( action : Ġ( String ) Ġ-> ĠUnit ) Ġ= ĊĠĠĠĠĠĠĠ Ġget Process ()?. error Stream ?. forEach ( action ) Ġ?: ĠLog . e ( TAG , Ġ" forEach Error Ġfailed ") ĊĊĠĠĠ Ġinternal Ġfun ĠforEach Command ( action : Ġ( String ) Ġ-> ĠUnit ) Ġ= ĊĠĠĠĠĠĠĠ Ġget Process ()?. inputStream ?. forEach ( action ) Ġ?: ĠLog . e ( TAG , Ġ" forEach Command Ġfailed ") ĊĊĠĠĠ Ġinternal Ġfun Ġpublish Response ( id : ĠInt , Ġdata Tree : ĠJson Element ) Ġ= Ġscope . launch Ġ{ ĊĠĠĠĠĠĠĠ Ġresponse Flow . emit ( Pair ( id , Ġdata Tree )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinternal Ġsuspend Ġfun Ġawait ( command : ĠCommand ): ĠJson Element Ġ= Ġsuspend Coroutine Ġ{ Ġcontinuation Ġ-> ĊĠĠĠĠĠĠĠ Ġscope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcommand . id Ġ= ĠrequestId . add AndGet ( 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġresponse Flow ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. on Subscription Ġ{ Ġsend ( command ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. first Ġ{ Ġit . first Ġ== Ġcommand . id Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. let Ġ{ Ġcontinuation . resume With ( Result . success ( it . second )) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinternal Ġfun Ġsend ( id : ĠInt , Ġerror : ĠError ) Ġ= Ġsend ( Command (" error ", Ġerror , Ġid )) ĊĊĠĠĠ Ġinternal Ġval Ġrunning : ĠBoolean ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġget Process ()?. running Ġ== Ġtrue ĊĊĠĠĠ Ġinternal Ġfun Ġsend ( command : ĠCommand ) Ġ= Ġscope . launch ( outgoing ) Ġ{ ĊĠĠĠĠĠĠĠ Ġget Process () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . output Stream ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . writer () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ" send ${ command . requestId }: Ġ$ command ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġappend ("${ gson . toJson ( command )}\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġflush () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ?: ĠLog . e ( TAG , Ġ" failed Ġto Ġsend : Ġ$ command ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠTAG Ġ= Ġ" Bridge " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠDEFAULT _ CHANNEL _ ID Ġ= Ġ" sms _ bridge _ service " ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġgson Ġ= Ġnew Gson () ĊĠĠĠĠĠĠĠ Ġval ĠINSTANCE Ġ= ĠBridge () ĊĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠProcess . running : ĠBoolean ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexit Value (). let Ġ{ ĠLog . w ( TAG , Ġ" exit ed : Ġ$ it ") Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIllegal Thread StateException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun ĠInputStream . forEach ( action : Ġ( String ) Ġ-> ĠUnit ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ"$ this ĠforEach ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreader (). buffered (). let Ġ{ Ġreader Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( element Ġin Ġreader . line Sequence ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaction ( element ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠLog . e ( TAG , Ġe ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreader . close () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ignored : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d ( TAG , Ġ"$ this Ġclosed ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun ĠString . to File (): ĠFile ? Ġ= ĠFile ( this ). take If Ġ{ Ġit . exists () Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun ĠString ?. exists (): ĠBoolean Ġ= Ġthis ?. let Ġ{ ĠFile ( it ) Ġ} ?. exists () Ġ== Ġtrue ĊĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠCommand . requestId : ĠString ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġif Ġ( id Ġ!= Ġnull Ġ&& Ġcommand Ġ!= Ġ" response ") Ġ" Ġ#$ id " Ġelse Ġ"" ĊĠĠĠ Ġ} Ċ }