/* Ċ Ġ* Ġ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 . layout inspector . legacy device Ċ Ċ import Ġcom . android . annotations . concurrency . Slow Ċ import Ġcom . android . dd m lib . Client Ċ import Ġcom . android . dd m lib . Debug View Dump Handler Ċ import Ġcom . android . tools . idea . layout inspector . model . Tree Loader Ċ import Ġcom . android . tools . idea . layout inspector . model . View Node Ċ import Ġcom . android . tools . idea . layout inspector . resource . Resource Lookup Ċ import Ġcom . android . tools . idea . layout inspector . transport . Inspector Client Ċ import Ġcom . google . common . annotations . Visible ForTesting Ċ import Ġcom . google . common . base . Charsets Ċ import Ġcom . google . common . collect . Lists Ċ import Ġcom . google . wire less . android . sdk . stats . Dynamic Layout Inspector Event . Dynamic Layout Inspector EventType Ċ import Ġcom . intellij . openapi . project . Project Ċ import Ġjava . io . BufferedReader Ċ import Ġjava . io . ByteArray InputStream Ċ import Ġjava . io . IOException Ċ import Ġjava . io . InputStream Reader Ċ import Ġjava . nio . ByteBuffer Ċ import Ġjava . util . Stack Ċ import Ġjava . util . concurrent . TimeUnit Ċ import Ġjava . util . concurrent . atomic . Atomic Reference Ċ import Ġjava . util . function . Bi Consumer Ċ import Ġjava . util . function . Binary Operator Ċ import Ġjava . util . function . Function Ċ import Ġjava . util . function . Supplier Ċ import Ġjava . util . stream . Collector Ċ import Ġjavax . image io . Image IO Ċ Ċ /** Ċ Ġ* ĠA Ġ[ Tree Loader ] Ġthat Ġcan Ġhandle Ġpre - api Ġ 2 9 Ġdevices . ĠLoads Ġthe Ġview Ġhierarchy Ġand Ġscreenshot Ġusing ĠD DM , Ġand Ġparses Ġit Ġinto Ġ[ View Node ] s Ċ Ġ*/ Ċ object ĠLegacy Tree Loader Ġ: ĠTree Loader Ġ{ ĊĊĠ Ġoverride Ġfun Ġload Component Tree ( ĊĠĠĠ Ġdata : ĠAny ?, Ġresource Lookup : ĠResource Lookup , Ġclient : ĠIns pector Client , Ġproject : ĠProject ĊĠ Ġ): ĠPair < View Node , ĠString >? Ġ{ ĊĠĠĠ Ġval Ġ( window Name , Ġupdater , Ġ_) Ġ= Ġdata Ġas ? ĠLegacy Event Ġ?: Ġreturn Ġnull ĊĠĠĠ Ġreturn Ġcapture ( client , Ġwindow Name , Ġupdater )?. let Ġ{ ĠPair ( it , Ġwindow Name ) Ġ} ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun ĠgetAll Window Ids ( data : ĠAny ?, Ġclient : ĠIns pector Client ): ĠList < String >? Ġ{ ĊĠĠĠ Ġif Ġ( data Ġis ĠLegacy Event ) Ġ{ ĊĠĠĠĠĠ Ġreturn Ġdata . all Windows ĊĠĠĠ Ġ} ĊĠĠĠ Ġval Ġlegacy Client Ġ= Ġclient Ġas ? ĠLegacy Client Ġ?: Ġreturn Ġnull ĊĠĠĠ Ġval Ġd dm Client Ġ= Ġlegacy Client . selected Client Ġ?: Ġreturn Ġnull ĊĠĠĠ Ġreturn ĠListView Roots Handler (). get Windows ( dd m Client , Ġ 5 , ĠTimeUnit . SECONDS ) ĊĠ Ġ} ĊĊĠ Ġ@ Slow ĊĠ Ġprivate Ġfun Ġcapture ( client : ĠIns pector Client , Ġwindow : ĠString , Ġproperties Updater : ĠLegacy Properties Provider . Updater ): ĠView Node ? Ġ{ ĊĠĠĠ Ġval Ġlegacy Client Ġ= Ġclient Ġas ? ĠLegacy Client Ġ?: Ġreturn Ġnull ĊĠĠĠ Ġval Ġd dm Client Ġ= Ġlegacy Client . selected Client Ġ?: Ġreturn Ġnull ĊĠĠĠ Ġval Ġhierarchy Handler Ġ= ĠCapture ByteArray Handler ( Debug View Dump Handler . CHUNK _ V UR T ) ĊĠĠĠ Ġd dm Client . dump View Hierarchy ( window , Ġfalse , Ġtrue , Ġfalse , Ġhierarchy Handler ) ĊĠĠĠ Ġproperties Updater . resource Lookup . dpi Ġ= Ġd dm Client . device . density ĊĠĠĠ Ġval Ġhierarchy Data Ġ= Ġhierarchy Handler . getData () Ġ?: Ġreturn Ġnull ĊĠĠĠ Ġval Ġ( root Node , Ġhash ) Ġ= Ġparse Live View Node ( hierarchy Data , Ġproperties Updater ) Ġ?: Ġreturn Ġnull ĊĠĠĠ Ġval Ġimage Handler Ġ= ĠCapture ByteArray Handler ( Debug View Dump Handler . CHUNK _ VU OP ) ĊĠĠĠ Ġd dm Client . capture View ( window , Ġhash , Ġimage Handler ) ĊĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠ Ġval Ġimage Data Ġ= Ġimage Handler . getData () ĊĠĠĠĠĠ Ġif Ġ( image Data Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġroot Node . image Bottom Ġ= ĠImage IO . read ( ByteArray InputStream ( image Data )) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠ Ġ// ĠWe Ġdidn 't Ġget Ġan Ġimage , Ġbut Ġstill Ġreturn Ġthe Ġhierarchy Ġand Ġproperties ĊĠĠĠ Ġ} ĊĠĠĠ Ġif Ġ( root Node . image Bottom Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠ Ġclient . log Event ( Dynamic Layout Inspector EventType . COMPAT IBILITY _ RENDER ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠ Ġclient . log Event ( Dynamic Layout Inspector EventType . COMPAT IBILITY _ RENDER _ NO _ PI CTURE ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġroot Node ĊĠ Ġ} ĊĊĠ Ġprivate Ġclass ĠCapture ByteArray Handler ( type : ĠInt ) Ġ: ĠDebug View Dump Handler ( type ) Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġm Data Ġ= ĠAtomic Reference < ByteArray >() ĊĊĠĠĠ Ġoverride Ġfun Ġhandle View Debug Result ( data : ĠByteBuffer ) Ġ{ ĊĠĠĠĠĠ Ġval Ġb Ġ= ĠByteArray ( data . remaining ()) ĊĠĠĠĠĠ Ġdata . get ( b ) ĊĠĠĠĠĠ Ġm Data . set ( b ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun ĠgetData (): ĠByteArray ? Ġ{ ĊĠĠĠĠĠ ĠwaitFor Result ( 1 5 , ĠTimeUnit . SECONDS ) ĊĠĠĠĠĠ Ġreturn Ġm Data . get () ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĠParses Ġthe Ġflat Ġstring Ġrepresentation Ġof Ġa Ġview Ġnode Ġand Ġreturns Ġthe Ġroot Ġnode . Ġ Ġ*/ ĊĠ Ġ@ Visible ForTesting ĊĠ Ġfun Ġparse Live View Node ( bytes : ĠByteArray , Ġproperty Updater : ĠLegacy Properties Provider . Updater ): ĠPair < View Node , ĠString >? Ġ Ġ{ ĊĠĠĠ Ġvar Ġroot Node And Hash : ĠPair < View Node , ĠString >? Ġ= Ġnull ĊĠĠĠ Ġvar Ġlast Node And Hash : ĠPair < View Node , ĠString >? Ġ= Ġnull ĊĠĠĠ Ġvar Ġlast Whitespace Count Ġ= ĠInteger . MIN _ VALUE ĊĠĠĠ Ġval Ġstack Ġ= ĠStack < View Node >() ĊĊĠĠĠ Ġval Ġinput Ġ= ĠBufferedReader ( ĊĠĠĠĠĠ ĠInputStreamReader ( ByteArray InputStream ( bytes ), ĠChar sets . UTF _ 8 ) ĊĠĠĠ Ġ) ĊĊĠĠĠ Ġfor Ġ( line Ġin Ġinput . lines (). collect ( Merge NewLine Collector )) Ġ{ ĊĠĠĠĠĠ Ġif Ġ(" DONE .". equals ( line , Ġignore Case Ġ= Ġtrue )) Ġ{ ĊĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ// Ġdetermine Ġparent Ġthrough Ġthe Ġlevel Ġof Ġnesting Ġby Ġcounting Ġwh ites p aces ĊĠĠĠĠĠ Ġvar Ġwhitespace Count Ġ= Ġ 0 ĊĠĠĠĠĠ Ġwhile Ġ( line [ whitespace Count ] Ġ== Ġ' Ġ') Ġ{ ĊĠĠĠĠĠĠĠ Ġwhitespace Count ++ ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ Ġif Ġ( last Whitespace Count Ġ< Ġwhitespace Count ) Ġ{ ĊĠĠĠĠĠĠĠ Ġstack . push ( last Node And Hash ?. first ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġelse Ġif Ġ(! stack . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcount Ġ= Ġlast Whitespace Count Ġ- Ġwhitespace Count ĊĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġcount ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġstack . pop () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ Ġlast Whitespace Count Ġ= Ġwhitespace Count ĊĠĠĠĠĠ Ġvar Ġparent : ĠView Node ? Ġ= Ġnull ĊĠĠĠĠĠ Ġif Ġ(! stack . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġparent Ġ= Ġstack . peek () ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġlast Node And Hash Ġ= Ġcreate View Node ( parent , Ġline . trim (), Ġproperty Updater ) ĊĠĠĠĠĠ Ġif Ġ( root Node And Hash Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġroot Node And Hash Ġ= Ġlast Node And Hash ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġroot Node And Hash ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġcreate View Node ( parent : ĠView Node ?, Ġdata : ĠString , Ġproperty Loader : ĠLegacy Properties Provider . Updater ): ĠPair < View Node , ĠString > Ġ{ ĊĠĠĠ Ġval Ġ( name , Ġdata Without Name ) Ġ= Ġdata . split ('@ ', Ġlimit Ġ= Ġ 2 ) ĊĠĠĠ Ġval Ġ( hash , Ġproperties ) Ġ= Ġdata Without Name . split (' Ġ', Ġlimit Ġ= Ġ 2 ) ĊĠĠĠ Ġval Ġhash Id Ġ= Ġhash . to Long OrNull ( 1 6 ) Ġ?: Ġ 0 ĊĠĠĠ Ġval Ġview Ġ= ĠView Node ( hash Id , Ġname , Ġnull , Ġ 0 , Ġ 0 , Ġ 0 , Ġ 0 , Ġnull , Ġ"", Ġ 0 ) ĊĠĠĠ Ġview . parent Ġ= Ġparent ĊĠĠĠ Ġparent ?. children ?. add ( view ) ĊĠĠĠ Ġproperty Loader . parse Properties ( view , Ġproperties ) ĊĠĠĠ Ġreturn ĠPair ( view , Ġ"$ name @ $ hash ") ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠA Ġcustom Ġcollector Ġthat Ġhandles Ġa Ġspecial Ġcase Ġsee Ġb / 7 9 1 8 3 6 2 3 ĊĠĠ Ġ* ĠIf Ġa Ġtext Ġfield Ġhas Ġtext Ġcontaining Ġa Ġnew Ġline Ġit 'll Ġcause Ġthe Ġview Ġnode Ġoutput Ġto Ġbe Ġsplit ĊĠĠ Ġ* Ġacross Ġmultiple Ġlines Ġso Ġthe Ġcollector Ġprocesses Ġthe Ġfile Ġoutput Ġand Ġmerge s Ġthose Ġback Ġinto Ġa ĊĠĠ Ġ* Ġsingle Ġline Ġso Ġwe Ġcan Ġcorrectly Ġcreate Ġview Ġnodes . ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġobject ĠMerge NewLine Collector Ġ: ĠCollector < String , ĠMutable List < String >, ĠList < String >> Ġ{ ĊĠĠĠ Ġoverride Ġfun Ġcharacteristics (): ĠSet < Collector . Character istics > Ġ{ ĊĠĠĠĠĠ Ġreturn Ġset Of ( Collector . Character istics . CON CURRENT ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġsupplier () Ġ= ĠSupplier < Mutable List < String >> Ġ{ Ġmutable ListOf () Ġ} ĊĠĠĠ Ġoverride Ġfun Ġfinish er () Ġ= ĠFunction < Mutable List < String >, ĠList < String >> Ġ{ Ġit . toList () Ġ} ĊĠĠĠ Ġoverride Ġfun Ġcombin er () Ġ= ĊĠĠĠĠĠ ĠBinary Operator < Mutable List < String >> Ġ{ Ġt , Ġu Ġ-> Ġt . apply Ġ{ Ġadd All ( u ) Ġ} Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġaccumulator () Ġ= ĠBi Consumer < Mutable List < String >, ĠString > Ġ{ Ġstring Group , Ġline Ġ-> ĊĠĠĠĠĠ Ġval Ġnew Line Ġ= Ġline . trim () ĊĠĠĠĠĠ Ġ// Ġadd Ġthe Ġoriginal Ġline Ġbecause Ġwe Ġneed Ġto Ġkeep Ġthe Ġspacing Ġto Ġdetermine Ġhierarchy ĊĠĠĠĠĠ Ġif Ġ( new Line . startsWith ("\\ n ")) Ġ{ ĊĠĠĠĠĠĠĠ Ġstring Group [ string Group . last Index ] Ġ= Ġstring Group . last () Ġ+ Ġline ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠ Ġstring Group . add ( line ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġclass ĠListView Roots Handler Ġ: ĊĠĠĠ ĠDebug View Dump Handler ( Debug View Dump Handler . CHUNK _ V UL W ) Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġview Roots Ġ= ĠLists . new Copy On Write ArrayList < String >() ĊĊĠĠĠ Ġoverride Ġfun Ġhandle View Debug Result ( data : ĠByteBuffer ) Ġ{ ĊĠĠĠĠĠ Ġval Ġn Windows Ġ= Ġdata . int ĊĊĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġn Windows ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġlen Ġ= Ġdata . int ĊĠĠĠĠĠĠĠ Ġview Roots . add ( getString ( data , Ġlen )) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Slow ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġfun Ġget Windows ( c : ĠClient , Ġtimeout : ĠLong , Ġunit : ĠTimeUnit ): ĠList < String > Ġ{ ĊĠĠĠĠĠ Ġc . list View Roots ( this ) ĊĠĠĠĠĠ ĠwaitFor Result ( timeout , Ġunit ) ĊĠĠĠĠĠ Ġreturn Ġview Roots ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ } Ċ