/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 1 9 ĠThe ĠAndroid ĠOpen ĠSource ĠProject Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ package Ġcom . android . tools . idea . app inspection . api Ċ Ċ import Ġcom . android . annotations . concurrency . Gu arded By Ċ import Ġcom . android . sdk lib . Android Version Ċ import Ġcom . android . tools . idea . app inspection . api . process . Process Descriptor Ċ import Ġcom . android . tools . idea . app inspection . api . process . Process Listener Ċ import Ġcom . android . tools . idea . app inspection . api . process . Process Notifier Ċ import Ġcom . android . tools . idea . app inspection . inspector . api . App Inspector Client Ċ import Ġcom . android . tools . idea . app inspection . inspector . api . App Inspector Jar Ċ import Ġcom . android . tools . idea . app inspection . internal . App Inspection Transport Ċ import Ġcom . android . tools . idea . app inspection . internal . attach App Inspection Target Ċ import Ġcom . android . tools . idea . concurrency . add Callback Ċ import Ġcom . android . tools . idea . concurrency . transform Ċ import Ġcom . android . tools . idea . concurrency . transform Async Ċ import Ġcom . android . tools . idea . transport . Transport Client Ċ import Ġcom . android . tools . idea . transport . manager . Transport Stream Channel Ċ import Ġcom . android . tools . idea . transport . manager . Transport Stream EventListener Ċ import Ġcom . android . tools . idea . transport . manager . Transport Stream Listener Ċ import Ġcom . android . tools . idea . transport . manager . Transport Stream Manager Ċ import Ġcom . android . tools . idea . transport . pol ler . Transport EventListener Ċ import Ġcom . android . tools . profiler . proto . Common Ċ import Ġcom . google . common . annotations . Visible ForTesting Ċ import Ġcom . google . common . util . concurrent . Future Callback Ċ import Ġcom . google . common . util . concurrent . F utures Ċ import Ġcom . google . common . util . concurrent . List enable Future Ċ import Ġcom . google . common . util . concurrent . More Executors Ċ import Ġjava . lang . Long . max Ċ import Ġjava . util . concurrent . Concurrent HashMap Ċ import Ġjava . util . concurrent . Executor Ċ import Ġjava . util . concurrent . ExecutorService Ċ import Ġjavax . annotation . concurrent . Thread Safe Ċ Ċ type alias ĠJar Cop ier Creator Ġ= Ġ( Common . Device ) Ġ-> ĠApp Inspection Jar Cop ier ? Ċ Ċ /** Ċ Ġ* ĠA Ġclass Ġthat Ġhosts Ġan Ġ[ App Inspection Discovery ] Ġand Ġmanages Ġprocesses Ġdiscovered Ġfrom Ġtransport Ġpipeline Ġand Ġother Ġsources . Ċ Ġ* Ċ Ġ* ĠDefinition : ĠAn Ġinspect able Ġprocess Ġis Ġa Ġprocess Ġthat Ġhas Ġcertain Ġinspection Ġflags Ġindicated Ġin Ġits Ġmanifest . ĠHowever , Ġcurrently Ġit Ġis Ċ Ġ* Ġsimply Ġa Ġprocess Ġthat Ġis Ġknown Ġby Ġtransport Ġpipeline Ġand Ġis Ġrunning Ġon Ġa ĠJVM TI - compatible Ġ( O +) Ġdevice . Ċ Ġ* ĠTODO ( b / 1 4 8 5 4 0 5 6 4 ): Ġtracks Ġthe Ġwork Ġneeded Ġto Ġmake Ġprocess Ġdetection Ġfe asible . Ċ Ġ* Ċ Ġ* ĠPro cesses Ġare Ġdiscovered Ġby Ġlistening Ġto Ġthe Ġtransport Ġpipeline Ġvia Ġ[ Transport EventListener ]. Ċ Ġ* Ċ Ġ* Ġ[ add Process Listener ] Ġallows Ġthe Ġfrontend Ġto Ġlisten Ġfor Ġnew Ġinspect able Ġprocesses . ĠMe ant Ġfor Ġpop ulating Ġthe ĠApp Inspection Ġcombo box . Ċ Ġ* Ċ Ġ* Ġ[ launch Inspector ] Ġis Ġused Ġby Ġthe Ġfrontend Ġto Ġlaunch Ġan Ġinspector . ĠIt Ġis Ġused Ġwhen Ġuser Ġselects Ġa Ġprocess Ġin Ġthe Ġcombo box . Ċ Ġ*/ Ċ @ Thread Safe Ċ class ĠApp Inspection Discovery Host ( ĊĠ Ġprivate Ġval Ġexecutor : ĠExecutor Service , ĊĠ Ġclient : ĠTransport Client , ĊĠ Ġprivate Ġval Ġmanager : ĠTransport Stream Manager , ĊĠ Ġprivate Ġval Ġcreate Jar Cop ier : ĠJar Cop ier Creator Ċ ): ĠProcess Notifier Ġ{ ĊĠ Ġ/** ĊĠĠ Ġ* ĠEn caps ulates Ġall Ġof Ġthe Ġparameters Ġthat Ġare Ġrequired Ġfor Ġlaunch ing Ġan Ġinspector . ĊĠĠ Ġ*/ ĊĠ Ġdata Ġclass ĠLaunch Parameters ( ĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠIdent ifies Ġthe Ġtarget Ġprocess Ġin Ġwhich Ġto Ġlaunch Ġthe Ġinspector . ĠIt Ġis Ġsupplied Ġby Ġ[ App Inspection Discovery Host ]. ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġval Ġprocess Descriptor : ĠProcess Descriptor , ĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠId Ġof Ġthe Ġinspector . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġval Ġinspector Id : ĠString , ĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠThe Ġ[ App Inspector Jar ] Ġcontaining Ġthe Ġlocation Ġof Ġthe Ġdex Ġto Ġbe Ġinstalled Ġon Ġdevice . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġval Ġinspector Jar : ĠApp Inspector Jar , ĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠThe Ġname Ġof Ġthe Ġstudio Ġproject Ġlaunch ing Ġthe Ġinspector . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġval ĠprojectName : ĠString ĊĠ Ġ) ĊĊĠ Ġ// ĠKeep Ġtrack Ġof Ġthe Ġlast _ active _ event _ timestamp Ġper Ġstream . ĠThis Ġensures Ġthat Ġin Ġthe Ġevent Ġthe Ġstream Ġis Ġdisconnected Ġand Ġconnected ĊĠ Ġ// Ġagain , ĠApp Inspection Ġwill Ġbe Ġable Ġto Ġfilter Ġout Ġand Ġignore Ġthe Ġevents Ġthat Ġhappened Ġin Ġthe Ġpast . ĊĠ Ġprivate Ġval Ġstream Last Active Time Ġ= ĠConcurrent HashMap < Long , ĠLong >() ĊĊĠ Ġprivate Ġval Ġdiscovery Ġ= ĠApp Inspection Discovery ( executor , Ġclient ) ĊĊĠ Ġprivate Ġval Ġstream Id Map Ġ= ĠConcurrent HashMap < Long , ĠTransport Stream Channel >() ĊĊĠ Ġprivate Ġdata Ġclass ĠStream Process Id Pair ( val Ġstream Id : ĠLong , Ġval Ġpid : ĠInt ) ĊĊĠ Ġprivate Ġclass ĠProcess Data Ġ{ ĊĠĠĠ Ġ@ Gu arded By (" process Data ") ĊĠĠĠ Ġval Ġprocesses Map Ġ= Ġmutable Map Of < Stream Process Id Pair , ĠProcess Descriptor >() ĊĊĠĠĠ Ġ@ Gu arded By (" process Data ") ĊĠĠĠ Ġval Ġprocess Listeners Ġ= Ġmutable Map Of < Process Listener , ĠExecutor >() ĊĠ Ġ} ĊĊĠ Ġprivate Ġval Ġprocess Data : ĠProcess Data Ġ= ĠProcess Data () ĊĊĠ Ġinit Ġ{ ĊĠĠĠ Ġregister Listeners For Discovery () ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠAdds Ġan Ġ[ Process Listener ] Ġto Ġdiscovery Ġservice . ĠListener Ġwill Ġreceive Ġfuture Ġconnections Ġwhen Ġthey Ġcome Ġonline . ĊĠĠ Ġ* ĊĠĠ Ġ* ĠThis Ġhas Ġthe Ġside Ġeffect Ġof Ġnotify ing Ġusers Ġof Ġall Ġexisting Ġlive Ġtargets Ġthe Ġdiscovery Ġservice Ġis Ġaware Ġof . ĊĠĠ Ġ*/ ĊĠ Ġoverride Ġfun Ġadd Process Listener ( ĊĠĠĠ Ġexecutor : ĠExecutor , ĊĠĠĠ Ġlistener : ĠProcess Listener ĊĠ Ġ) Ġ{ ĊĠĠĠ Ġsynchronized ( process Data ) Ġ{ ĊĠĠĠĠĠ Ġif Ġ( process Data . process Listeners . put If Absent ( listener , Ġexecutor ) Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġprocess Data . processes Map . values . forEach Ġ{ Ġexecutor . execute Ġ{ Ġlistener . on Process Connected ( it ) Ġ} Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠRemoves Ġa Ġ[ Process Listener ] Ġand Ġso Ġstops Ġit Ġfrom Ġhe aring Ġfuture Ġprocess Ġevents . ĊĠĠ Ġ*/ ĊĠ Ġoverride Ġfun Ġremove Process Listener ( listener : ĠProcess Listener ): ĠUnit Ġ= Ġsynchronized ( process Data ) Ġ{ Ġprocess Data . process Listeners . remove ( listener ) Ġ} ĊĊĊĠ Ġ/** ĊĠĠ Ġ* ĠLa unches Ġan Ġinspector Ġbased Ġon Ġthe Ġinformation Ġgiven Ġby Ġ[ params ]. ĊĠĠ Ġ* ĊĠĠ Ġ* Ġ[ params ] Ġcontains Ġinformation Ġsuch Ġas Ġthe Ġinspector 's Ġid Ġand Ġdex Ġlocation , Ġas Ġwell Ġas Ġthe Ġtargeted Ġprocess 's Ġdescriptor . ĊĠĠ Ġ* Ġ[ creator ] Ġis Ġa Ġcallback Ġused Ġto Ġset Ġup Ġa Ġclient 's Ġ[ App Inspector Client . raw EventListener ]. ĊĠĠ Ġ*/ ĊĠ Ġfun Ġ< T Ġ: ĠApp Inspector Client > Ġlaunch Inspector ( params : ĠLaunch Parameters , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcreator : Ġ( App Inspector Client . Command Messenger ) Ġ-> ĠT ): ĠList enable Future < App Inspector Client > Ġ{ ĊĠĠĠ Ġstream Id Map [ params . process Descriptor . stream . stream Id ]?. let Ġ{ Ġstream Channel Ġ-> ĊĠĠĠĠĠ Ġcreate Jar Cop ier ( params . process Descriptor . stream . device )?. let Ġ{ Ġjar Cop ier Ġ-> ĊĠĠĠĠĠĠĠ Ġreturn Ġdiscovery . launch Inspector ( params , Ġcreator , Ġjar Cop ier , Ġstream Channel ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn ĠF utures . immediate Failed Future ( ĊĠĠĠĠĠ ĠProcess No Long er Exists Exception (" Cannot Ġattach Ġto Ġprocess Ġbecause Ġthe Ġdevice Ġdoes Ġnot Ġexist . ĠProcess : Ġ${ params . process Descriptor } ")) ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠDis poses Ġall Ġof Ġthe Ġcurrently Ġactive Ġinspect ors Ġassociated Ġto Ġproject Ġwith Ġprovided Ġ[ projectName ]. ĊĠĠ Ġ* ĊĠĠ Ġ* ĠThis Ġis Ġused Ġby Ġthe Ġservice Ġto Ġclean Ġup Ġafter Ġprojects Ġwhen Ġthey Ġare Ġno Ġlonger Ġinterested Ġin Ġa Ġprocess , Ġor Ġwhen Ġthey Ġexit . ĊĠĠ Ġ*/ ĊĠ Ġfun Ġdispose Clients ( projectName : ĠString ) Ġ{ ĊĠĠĠ Ġdiscovery . dispose Clients ( projectName ) ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠRegister Ġlisteners Ġto Ġreceive Ġstream Ġand Ġprocess Ġevents Ġfrom Ġtransport Ġpipeline . ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġfun Ġregister Listeners For Discovery () Ġ{ ĊĠĠĠ Ġ// ĠCreate Ġlistener Ġfor ĠST REAM Ġconnected ĊĠĠĠ Ġmanager . add Stream Listener ( object Ġ: ĠTransport Stream Listener Ġ{ ĊĠĠĠĠĠ Ġoverride Ġfun Ġon Stream Connected ( stream Channel : ĠTransport Stream Channel ) Ġ{ ĊĠĠĠĠĠĠĠ Ġstream Id Map [ stream Channel . stream . stream Id ] Ġ= Ġstream Channel ĊĠĠĠĠĠĠĠ Ġval Ġstream Last Event Timestamp Ġ= Ġstream Last Active Time [ stream Channel . stream . stream Id ]?. let Ġ{ Ġ{ Ġit Ġ+ Ġ 1 } Ġ} Ġ?: Ġ{ ĠLong . MIN _ VALUE Ġ} ĊĠĠĠĠĠĠĠ Ġstream Channel . register Stream EventListener ( ĊĠĠĠĠĠĠĠĠĠ ĠTransport Stream EventListener ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevent Kind Ġ= ĠCommon . Event . Kind . PROCESS , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexecutor Ġ= Ġexecutor , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfilter Ġ= Ġ{ Ġit . process . has Process Started () Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠ ĠstartTime Ġ= Ġstream Last Event Timestamp ĊĠĠĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġprocess Ġ= Ġit . process . process Started . process ĊĠĠĠĠĠĠĠĠĠĠĠ Ġadd Process ( stream Channel , Ġprocess ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġset Stream Last Active Time ( stream Channel . stream . stream Id , Ġit . timestamp ) ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġstream Channel . register Stream EventListener ( ĊĠĠĠĠĠĠĠĠĠ ĠTransport Stream EventListener ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġevent Kind Ġ= ĠCommon . Event . Kind . PROCESS , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexecutor Ġ= Ġexecutor , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfilter Ġ= Ġ{ Ġ! it . process . has Process Started () Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠ ĠstartTime Ġ= Ġstream Last Event Timestamp ĊĠĠĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġremove Process ( stream Channel . stream . stream Id , Ġit . groupId . toInt ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġset Stream Last Active Time ( stream Channel . stream . stream Id , Ġit . timestamp ) ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ Ġoverride Ġfun Ġon Stream Disconnected ( stream Channel : ĠTransport Stream Channel ) Ġ{ ĊĠĠĠĠĠĠĠ Ġstream Id Map . remove ( stream Channel . stream . stream Id ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}, Ġexecutor ) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġset Stream Last Active Time ( stream Id : ĠLong , Ġtimestamp : ĠLong ) Ġ{ ĊĠĠĠ Ġstream Last Active Time [ stream Id ] Ġ= Ġmax ( timestamp , Ġstream Last Active Time [ stream Id ] Ġ Ġ?: ĠLong . MIN _ VALUE ) ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠAdds Ġa Ġprocess Ġto Ġinternal Ġcache . ĠThis Ġis Ġcalled Ġwhen Ġtransport Ġpipeline Ġis Ġaware Ġof Ġa Ġnew Ġprocess . ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġfun Ġadd Process ( stream Channel : ĠTransport Stream Channel , Ġprocess : ĠCommon . Process ) Ġ{ ĊĠĠĠ Ġsynchronized ( process Data ) Ġ{ ĊĠĠĠĠĠ Ġprocess Data . processes Map . compute If Absent ( Stream Process Id Pair ( stream Channel . stream . stream Id , Ġprocess . pid )) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġdescriptor Ġ= ĠProcess Descriptor ( stream Channel . stream , Ġprocess ) ĊĠĠĠĠĠĠĠ Ġif Ġ( descriptor . is Inspect able ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġprocess Data . process Listeners . forEach Ġ{ Ġ( listener , Ġexecutor ) Ġ-> Ġexecutor . execute Ġ{ Ġlistener . on Process Connected ( descriptor ) Ġ} Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġdescriptor ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠReturn Ġtrue Ġif Ġthe Ġprocess Ġit Ġrepresents Ġis Ġinspect able . ĊĠĠ Ġ* ĊĠĠ Ġ* ĠCurrently , Ġa Ġprocess Ġis Ġdee med Ġinspect able Ġif Ġthe Ġdevice Ġit 's Ġrunning Ġon Ġis ĠO + Ġand Ġif Ġit 's Ġdebug gable . ĠThe Ġlatter Ġcondition Ġis ĊĠĠ Ġ* Ġguaranteed Ġto Ġbe Ġtrue Ġbecause Ġtransport Ġpipeline Ġonly Ġprovides Ġdebug gable Ġprocesses , Ġso Ġthere Ġis Ġno Ġneed Ġto Ġcheck . ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġfun ĠProcess Descriptor . is Inspect able (): ĠBoolean Ġ{ ĊĠĠĠ Ġreturn Ġstream . device . api Level Ġ>= ĠAndroid Version . Version Codes . O ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠRemoves Ġa Ġprocess Ġfrom Ġinternal Ġcache . ĠThis Ġfunction Ġis Ġcalled Ġwhen Ġa Ġprocess Ġgoes Ġoffline . ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġfun Ġremove Process ( stream Id : ĠLong , Ġprocess Id : ĠInt ) Ġ{ ĊĠĠĠ Ġsynchronized ( process Data ) Ġ{ ĊĠĠĠĠĠ Ġprocess Data . processes Map . remove ( Stream Process Id Pair ( stream Id , Ġprocess Id )) ?. let Ġ{ Ġdescriptor Ġ-> ĊĠĠĠĠĠĠĠ Ġdiscovery . remove Process ( descriptor ) ĊĠĠĠĠĠĠĠ Ġprocess Data . process Listeners . forEach Ġ{ Ġ( listener , Ġexecutor ) Ġ-> Ġexecutor . execute Ġ{ Ġlistener . on Process Disconnected ( descriptor ) Ġ} Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠThrow n Ġwhen Ġtrying Ġto Ġlaunch Ġan Ġinspector Ġon Ġa Ġprocess Ġthat Ġno Ġlonger Ġexists . Ċ Ġ* Ċ Ġ* ĠNote : ĠThis Ġmay Ġnot Ġnecessarily Ġsignal Ġsomething Ġis Ġbroken . ĠWe Ġexpect Ġthis Ġto Ġhappen Ġoccasion ally Ġdue Ġto Ġbad Ġtiming . ĠFor Ġexample : Ġuser Ċ Ġ* Ġselects Ġa Ġprocess Ġfor Ġinspection Ġon Ġdevice ĠX Ġright Ġwhen ĠX Ġis Ġshut ting Ġdown . Ċ Ġ*/ Ċ class ĠProcess No Long er Exists Exception ( message : ĠString ): ĠException ( message ) Ċ Ċ /** Ċ Ġ* ĠA Ġclass Ġwhich Ġkeeps Ġtrack Ġof Ġlive Ġ[ App Inspection Target ] Ġand Ġ[ App Inspector Client ]. ĠIt Ġexposes Ġ[ launch Inspector ] Ġthat Ġallows Ġfor Ġlaunch ing Ċ Ġ* Ġof Ġinspection Ġtargets Ġand Ġindividual Ġinspect ors . Ċ Ġ*/ Ċ @ Thread Safe Ċ class ĠApp Inspection Discovery Ġinternal Ġconstructor ( ĊĠ Ġprivate Ġval Ġexecutor : ĠExecutor Service , ĊĠ Ġprivate Ġval Ġtransport Client : ĠTransport Client Ċ ) Ġ{ ĊĠ Ġprivate Ġval Ġlock Ġ= ĠAny () ĊĊĠ Ġ@ Visible ForTesting ĊĠ Ġ@ Gu arded By (" lock ") ĊĠ Ġinternal Ġval Ġtargets Ġ= ĠConcurrent HashMap < Process Descriptor , ĠList enable Future < App Inspection Target >>() ĊĊĠ Ġ@ Gu arded By (" lock ") ĊĠ Ġ@ Visible ForTesting ĊĠ Ġinternal Ġval Ġclients Ġ= ĠConcurrent HashMap < App Inspection Discovery Host . Launch Parameters , ĠList enable Future < App Inspector Client >>() ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠAt tempts Ġto Ġconnect Ġto Ġa Ġprocess Ġon Ġdevice Ġspecified Ġby Ġ[ process Descriptor ]. ĠReturns Ġa Ġfuture Ġof Ġ[ App Inspection Target ] Ġwhich Ġcan Ġbe ĊĠĠ Ġ* Ġused Ġto Ġlaunch Ġinspector Ġconnections . ĊĠĠ Ġ*/ ĊĠ Ġ@ Gu arded By (" lock ") ĊĠ Ġprivate Ġfun Ġattach To Process ( ĊĠĠĠ Ġprocess Descriptor : ĠProcess Descriptor , ĊĠĠĠ Ġjar Cop ier : ĠApp Inspection Jar Cop ier , ĊĠĠĠ Ġstream Channel : ĠTransport Stream Channel ĊĠ Ġ): ĠList enable Future < App Inspection Target > Ġ{ ĊĠĠĠ Ġreturn Ġtargets . compute If Absent ( process Descriptor ) Ġ{ ĊĠĠĠĠĠ Ġval Ġtransport Ġ= ĊĠĠĠĠĠĠĠ ĠApp Inspection Transport ( transport Client , Ġprocess Descriptor . stream , Ġprocess Descriptor . process , Ġexecutor , Ġstream Channel ) ĊĠĠĠĠĠ Ġattach App Inspection Target ( transport , Ġjar Cop ier ) ĊĠĠĠ Ġ}. also Ġ{ ĊĠĠĠĠĠ Ġit . add Callback ( More Executors . direct Executor (), Ġobject Ġ: ĠFuture Callback < App Inspection Target > Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun ĠonSuccess ( result : ĠApp Inspection Target ?) Ġ{} ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Failure ( t : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġtargets . remove ( process Descriptor ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ}) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠLa unches Ġan Ġinspector Ġusing Ġthe Ġinformation Ġgiven Ġby Ġ[ launch Parameters ]. ĠReturns Ġa Ġfuture Ġof Ġthe Ġlaunched Ġ[ App Inspector Client ]. ĊĠĠ Ġ* ĊĠĠ Ġ* ĠThis Ġcan Ġreturn Ġan Ġexisting Ġlive Ġ[ App Inspector Client ] Ġif Ġan Ġidentical Ġinspector Ġwas Ġlaunched Ġon Ġthe Ġsame Ġprocess . ĊĠĠ Ġ*/ ĊĠ Ġinternal Ġfun Ġlaunch Inspector ( ĊĠĠĠ Ġlaunch Parameters : ĠApp Inspection Discovery Host . Launch Parameters , ĊĠĠĠ Ġcreator : Ġ( App Inspector Client . Command Messenger ) Ġ-> ĠApp Inspector Client , ĊĠĠĠ Ġjar Cop ier : ĠApp Inspection Jar Cop ier , ĊĠĠĠ Ġstream Channel : ĠTransport Stream Channel ĊĠ Ġ): ĠList enable Future < App Inspector Client > Ġ= Ġsynchronized ( lock ) Ġ{ ĊĠĠĠ Ġclients . compute If Absent ( launch Parameters ) Ġ{ ĊĠĠĠĠĠ Ġattach To Process ( launch Parameters . process Descriptor , Ġjar Cop ier , Ġstream Channel ). transform Async ( ĊĠĠĠĠĠĠĠ ĠMore Executors . direct Executor ()) Ġ{ Ġtarget Ġ-> ĊĠĠĠĠĠĠĠ Ġtarget . launch Inspector ( launch Parameters . inspector Id , Ġlaunch Parameters . inspector Jar , Ġlaunch Parameters . projectName , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcreator ). transform Ġ{ Ġclient Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġclient . add Service EventListener ( object Ġ: ĠApp Inspector Client . Service EventListener Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Dispose () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclients . remove ( launch Parameters ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ}, ĠMore Executors . direct Executor ()) ĊĠĠĠĠĠĠĠĠĠ Ġclient ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ}. also Ġ{ ĊĠĠĠĠĠĠĠ Ġit . add Callback ( More Executors . direct Executor (), Ġobject Ġ: ĠFuture Callback < App Inspector Client > Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun ĠonSuccess ( result : ĠApp Inspector Client ?) Ġ{} ĊĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Failure ( t : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclients . remove ( launch Parameters ) ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠCalled Ġwhen Ġa Ġprocess Ġhas Ġterminated . ĠThis Ġwill Ġclean Ġup Ġ[ App Inspection Target ] Ġand Ġall Ġclients Ġassociated Ġwith Ġthe Ġprocess . ĊĠĠ Ġ* ĊĠĠ Ġ* ĠNote : Ġthis Ġdoes Ġnot Ġtry Ġto Ġdispose Ġclients Ġbecause Ġit 's Ġtoo Ġlate . ĊĠĠ Ġ*/ ĊĠ Ġinternal Ġfun Ġremove Process ( process : ĠProcess Descriptor ) Ġ{ ĊĠĠĠ Ġsynchronized ( lock ) Ġ{ ĊĠĠĠĠĠ Ġtargets . remove ( process )?. let Ġ{ ĊĠĠĠĠĠĠĠ Ġclients . keys . removeAll Ġ{ Ġlaunch Param Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġlaunch Param . process Descriptor Ġ== Ġprocess ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠDispose Ġclients Ġbelong ing Ġto Ġthe Ġproject Ġthat Ġmatches Ġthe Ġprovided Ġ[ projectName ]. ĊĠĠ Ġ*/ ĊĠ Ġinternal Ġfun Ġdispose Clients ( projectName : ĠString ) Ġ{ ĊĠĠĠ Ġsynchronized ( lock ) Ġ{ ĊĠĠĠĠĠ Ġclients . filter Keys Ġ{ Ġit . projectName Ġ== ĠprojectName Ġ} ĊĠĠĠĠĠĠĠ Ġ. values . forEach Ġ{ Ġif Ġ( it . is Done ) Ġit . get (). messenger . dispose Inspector () Ġelse Ġit . cancel ( false ) Ġ} ĊĠĠĠĠĠ Ġclients . keys . removeAll Ġ{ Ġit . projectName Ġ== ĠprojectName Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ }