package Ġcom . av ito . android . runner . devices . internal . kubernetes Ċ Ċ import Ġcom . av ito . android . Result Ċ import Ġcom . av ito . android . runner . devices . internal . Android Debug Bridge Ċ import Ġcom . av ito . android . runner . devices . internal . E mul ators Logs Reporter Ċ import Ġcom . av ito . android . runner . devices . internal . Remote Device Ċ import Ġcom . av ito . android . runner . devices . internal . Reservation Client Ċ import Ġcom . av ito . android . runner . devices . model . Reservation Data Ċ import Ġcom . av ito . k 8 s . Kubernetes Api Ċ import Ġcom . av ito . k 8 s . model . Kube Pod Ċ import Ġcom . av ito . logger . LoggerFactory Ċ import Ġcom . av ito . logger . create Ċ import Ġcom . av ito . runner . service . worker . device . Device Coordinate Ċ import Ġcom . av ito . runner . service . worker . device . Serial Ċ import Ġkotlinx . coroutines . Coroutine Dispatcher Ċ import Ġkotlinx . coroutines . Coroutine Name Ċ import Ġkotlinx . coroutines . Coroutine Scope Ċ import Ġkotlinx . coroutines . Dispatch ers Ċ import Ġkotlinx . coroutines . Experimental Cor outines Api Ċ import Ġkotlinx . coroutines . channels . Channel Ċ import Ġkotlinx . coroutines . channels . Receive Channel Ċ import Ġkotlinx . coroutines . channels . consume Each Ċ import Ġkotlinx . coroutines . channels . distinct By Ċ import Ġkotlinx . coroutines . channels . filter Ċ import Ġkotlinx . coroutines . channels . map Ċ import Ġkotlinx . coroutines . channels . toList Ċ import Ġkotlinx . coroutines . delay Ċ import Ġkotlinx . coroutines . launch Ċ import Ġkotlinx . coroutines . sync . Mutex Ċ import Ġkotlinx . coroutines . sync . with Lock Ċ import Ġkotlinx . coroutines . with Context Ċ import Ġkotlin . coroutines . coroutine Context Ċ Ċ /** Ċ Ġ* ĠYou Ġshould Ġknow Ġthat Ġcancel ing Ġjobs Ġmanually Ġor Ġvia Ġthrowing Ġexception Ċ Ġ* Ġwill Ġcancel Ġwhole Ġparent Ġjob Ġand Ġall Ġconsuming Ġchannels . Ċ Ġ* Ċ Ġ* ĠIn Ġ[ Kubernetes Reservation Client ] Ġcase Ġpods Channel Ġwill Ġclose Ġautomatically Ġwhen Ġ[ claim ] Ġjob Ġfailed Ġor Ġcanceled Ċ Ġ*/ Ċ @ Opt In ( Experimental Cor outines Api :: class ) Ċ internal Ġclass ĠKubernetes Reservation Client ( ĊĠĠĠ Ġprivate Ġval Ġandroid Debug Bridge : ĠAndroid Debug Bridge , ĊĠĠĠ Ġprivate Ġval Ġkubernetes Api : ĠKubernetes Api , ĊĠĠĠ Ġprivate Ġval Ġem ulators Logs Reporter : ĠE mul ators Logs Reporter , ĊĠĠĠ Ġlogger Factory : ĠLoggerFactory , ĊĠĠĠ Ġprivate Ġval Ġreservation Deployment Factory : ĠReser vation Deployment Factory , ĊĠĠĠ Ġprivate Ġval Ġdispatcher : ĠCor outine Dispatcher Ġ= ĠDispatch ers . IO , ĊĠĠĠ Ġprivate Ġval Ġpods Query Interval Ms : ĠLong Ġ= Ġ 5 0 0 0 L Ċ ) Ġ: ĠReser vation Client Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġlogger Ġ= Ġlogger Factory . create < Kubernetes Reservation Client >() ĊĊĠĠĠ Ġprivate Ġvar Ġstate : ĠState Ġ= ĠState . Id ling ĊĊĠĠĠ Ġprivate Ġval Ġlock Ġ= ĠMutex () ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġclaim ( ĊĠĠĠĠĠĠĠ Ġre servations : ĠCollection < Reservation Data > ĊĠĠĠ Ġ): ĠReser vation Client . Claim Result Ġ{ ĊĠĠĠĠĠĠĠ Ġrequire ( re servations . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" Must Ġhave Ġat Ġleast Ġone Ġreservation Ġbut Ġempty " ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġlock . with Lock Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO Ġclose Ġserial s Channel ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġserial s Channel Ġ= ĠChannel < Device Coordinate >( Channel . UN LIMIT ED ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( state Ġ! is ĠState . Id ling ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalStateException (" Unable Ġclaim Ġreservation . ĠState Ġis Ġalready Ġstarted ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwith ( Coroutine Scope ( coroutine Context Ġ+ Ġdispatcher )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlaunch ( Coroutine Name (" main - reservation ")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpods Channel Ġ= ĠChannel < Kube Pod >( Channel . UN LIMIT ED ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdeployments Channel Ġ= ĠChannel < String >( re servations . size ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . Reser ving ( pods Ġ= Ġpods Channel , Ġdeployments Ġ= Ġdeployments Channel ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġre servations . forEach Ġ{ Ġreservation Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlaunch ( Coroutine Name (" create - deployment ")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcreate Deployment ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreservation , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdeployments Channel , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpods Channel , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġserial s Channel ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinitialize Devices ( pods Channel , Ġserial s Channel ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠReser vation Client . Claim Result ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdevice Coordinates Ġ= Ġserial s Channel ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġcreate Deployment ( ĊĠĠĠĠĠĠĠ Ġreservation : ĠReser vation Data , ĊĠĠĠĠĠĠĠ Ġdeployments Channel : ĠChannel < String >, ĊĠĠĠĠĠĠĠ Ġpods Channel : ĠChannel < Kube Pod >, ĊĠĠĠĠĠĠĠ Ġserial s Channel : ĠChannel < Device Coordinate > ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġdeployment Ġ= Ġreservation Deployment Factory . create Deployment ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnamespace Ġ= Ġkubernetes Api . namespace , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreservation Ġ= Ġreservation ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġval Ġdeployment Name Ġ= Ġlock . with Lock Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdeployment Name Ġ= Ġdeployment . metadata . name ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdeployments Channel . send ( deployment Name ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġkubernetes Api . create Deployment ( deployment ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdeployment Name ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġlisten Pods From Deployment ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdeployment Name Ġ= Ġdeployment Name , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpods Channel Ġ= Ġpods Channel , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġserial s Channel Ġ= Ġserial s Channel ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠCor outine Scope . initialize Devices ( ĊĠĠĠĠĠĠĠ Ġpods Channel : ĠReceive Channel < Kube Pod >, ĊĠĠĠĠĠĠĠ Ġserial s Channel : ĠChannel < Device Coordinate > ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġlaunch ( Coroutine Name (" waiting - pods ")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ@ Suppress (" DE PREC ATION ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpods Channel ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( serial s Channel . is Closed For Send ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . debug (" cancel Ġwaiting - pods ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpods Channel . cancel () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . phase Ġis ĠKube Pod . Pod Phase . Running Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. distinct By Ġ{ Ġit . name Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. consume Each Ġ{ Ġpod Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlaunch ( Coroutine Name (" boot - pod -${ pod . name } ")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpod . initialize Device () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. on Success Ġ{ Ġdevice Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdevice . send To ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpod . name , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġserial s Channel ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . debug (" initialize Devices Ġfinished ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun ĠRemote Device . send To ( ĊĠĠĠĠĠĠĠ Ġpod Name : ĠString , ĊĠĠĠĠĠĠĠ Ġserial s : ĠChannel < Device Coordinate >, ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( serial s . is Closed For Send ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . debug (" Pod Ġ$ pod Name Ġboot Ġdevice Ġbut Ġserial s Ġchannel Ġclosed ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġem ulators Logs Reporter . redirect Log cat ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġemulator Name Ġ= Ġserial , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdevice Ġ= Ġthis ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġserial s . send ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠDevice Coordinate . Kubernetes ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġserial Ġ= Ġserial , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpod Name Ġ= Ġpod Name ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġlogger . debug (" Pod Ġ$ pod Name Ġsent Ġoutside Ġfor Ġfurther Ġusage ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun ĠKube Pod . initialize Device (): ĠResult < Remote Device > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġpod Name Ġ= Ġname ĊĠĠĠĠĠĠĠ Ġlogger . debug (" Found Ġnew Ġpod : Ġ$ pod Name ") ĊĠĠĠĠĠĠĠ Ġreturn Ġboot Device (). on Failure Ġ{ Ġerror Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . warn ( initialize Failure Message ( pod Name , Ġip ), Ġerror ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġis Deleted Ġ= Ġkubernetes Api . delete Pod ( pod Name ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . debug (" Pod Ġ$ pod Name Ġis Ġdeleted : Ġ$ is Deleted ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġinitialize Failure Message ( pod Name : ĠString , Ġpod Ip : ĠString ?): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġbuild String Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġappend (" Pod Ġ$ pod Name Ġcan 't Ġload Ġdevice . ĠDis connect Ġand Ġdelete .") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! pod Ip . isNull Or Blank ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġappend Line () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġappend (" Check Ġdevice Ġlogs Ġin Ġartifacts : Ġ${ em ulators Logs Reporter . get LogFile ( pod Ip )} ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġremove ( pod Name : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġwith Context ( Coroutine Name (" delete - pod -$ pod Name ") Ġ+ Ġdispatcher ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġkubernetes Api . delete Pod ( pod Name ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġrelease () Ġ= Ġwith Context ( dispatcher ) Ġ{ ĊĠĠĠĠĠĠĠ Ġlock . with Lock Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstate Ġ= Ġstate ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( state Ġ! is ĠState . Reser ving ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO : Ġcheck Ġon Ġclient Ġside Ġbefore hand ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO Ġthis Ġleads Ġto Ġdeployment Ġleak ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalStateException (" Unable Ġto Ġstop Ġreservation Ġjob . ĠHas n 't Ġstarted Ġyet ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate . pods . close () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate . deployments . close () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( deployment Name Ġin Ġstate . deployments . toList ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlaunch ( Coroutine Name (" delete - deployment -$ deployment Name ")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġkubernetes Api . get Pods ( deployment Name ). fold ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ{ Ġpods Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrunning Pods Ġ= Ġpods . filter Ġ{ Ġit . phase Ġis ĠKube Pod . Pod Phase . Running Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( running Pods . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . debug (" Save Ġem ulators Ġlogs Ġfor Ġdeployment : Ġ$ deployment Name ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( pod Ġin Ġrunning Pods ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlaunch ( Coroutine Name (" get - pod - logs -${ pod . name } ")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpod Name Ġ= Ġpod . name ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpod . getDevice (). on Success Ġ{ Ġdevice Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġserial Ġ= Ġdevice . serial ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġem ulators Logs Reporter . report Em ulator Logs ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpod Ġ= Ġpod , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġemulator Name Ġ= Ġserial , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog Ġ= Ġkubernetes Api . get Pod Logs ( pod Name ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( throwable : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO Ġmust Ġbe Ġfixed Ġafter Ġadding Ġaff inity Ġto ĠPO D ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpod Description Ġ= Ġkubernetes Api . get Pod Description ( pod Name ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . warn ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Get Ġlogs Ġfrom Ġemulator Ġfailed ; Ġpod =$ pod Name ; Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" pod Description =$ pod Description ; Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" container Ġserial =$ serial ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrowable ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdevice . disconnect (). fold ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ{ Ġlogger . debug (" Device : Ġ$ serial Ġdisconnected ") Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ{ Ġerror Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . warn (" Failed Ġto Ġdisconnect Ġdevice : Ġ$ serial ", Ġerror ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ{ Ġerror Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . warn (" Can 't Ġget Ġpods Ġwhen Ġrelease ", Ġerror ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġkubernetes Api . delete Deployment ( deployment Name ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis @ Kubernetes Reservation Client . state Ġ= ĠState . Id ling ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġlogger . debug (" release Ġfinished ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun ĠKube Pod . boot Device (): ĠResult < Remote Device > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġget Device () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. flatMap Ġ{ Ġdevice Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdevice . waitFor Boot () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġdevice Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. on Failure Ġ{ Ġdevice . disconnect () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠKube Pod . getDevice (): ĠResult < Remote Device > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠResult . try Catch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpod Ip Ġ= Ġip ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrequire NotNull ( pod Ip ) Ġ{ Ġ" Pod : Ġ$ name Ġmust Ġhave Ġan ĠIP " Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġserial Ġ= Ġemulator Serial Name ( name Ġ= Ġpod Ip ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġandroid Debug Bridge . get Remote Device ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġserial Ġ= Ġserial ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġlisten Pods From Deployment ( ĊĠĠĠĠĠĠĠ Ġdeployment Name : ĠString , ĊĠĠĠĠĠĠĠ Ġpods Channel : ĠChannel < Kube Pod >, ĊĠĠĠĠĠĠĠ Ġserial s Channel : ĠChannel < Device Coordinate > ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġlogger . debug (" Start Ġlistening Ġdevices Ġfor Ġ$ deployment Name ") ĊĊĠĠĠĠĠĠĠ Ġvar Ġnext Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġwhile Ġ( next ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlock . with Lock Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! pods Channel . is Closed For Send ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( val Ġresult Ġ= Ġkubernetes Api . get Pods ( deployment Name )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠResult . Success Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . value . forEach Ġ{ Ġpod Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpods Channel . send ( pod ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdelay ( pods Query Interval Ms ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠResult . Failure Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnext Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . critical (" Error Ġget Ġpods ", Ġresult . throwable ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpods Channel . cancel () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġserial s Channel . close () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnext Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġlogger . debug (" listen Pods From Deployment Ġfinished , Ġ[ deployment Name =$ deployment Name ]") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġemulator Serial Name ( name : ĠString ): ĠSerial . Remote Ġ= ĠSerial . Remote ("$ name :$ AD B _ DEFAULT _ PORT ") ĊĊĠĠĠ Ġprivate Ġsealed Ġclass ĠState Ġ{ ĊĠĠĠĠĠĠĠ Ġclass ĠReser ving ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpods : ĠChannel < Kube Pod >, ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdeployments : ĠChannel < String > ĊĠĠĠĠĠĠĠ Ġ) Ġ: ĠState () ĊĊĠĠĠĠĠĠĠ Ġobject ĠId ling Ġ: ĠState () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ċ } Ċ Ċ private Ġconst Ġval ĠA DB _ DEFAULT _ PORT Ġ= Ġ 5 5 5 5 Ċ