/* Ċ Ġ* Ġ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 . build . gradle . internal . tasks Ċ Ċ import Ġcom . android . build . gradle . internal . transforms . No Op Message Receiver Ċ import Ġcom . android . builder . core . Variant Type Impl Ċ import Ġcom . android . builder . dex ing . Dex ing Type Ċ import Ġcom . android . builder . dex ing . Pro guard Output Files Ċ import Ġcom . android . test utils . Test Classes Generator Ċ import Ġcom . android . test utils . Test Inputs Generator Ċ import Ġcom . android . test utils . TestUtils Ċ import Ġcom . android . test utils . apk . Dex Ċ import Ġcom . android . test utils . truth . Dex Subject . assertThat Ċ import Ġcom . android . test utils . truth . Dex Subject . assertThat Dex Ċ import Ġcom . android . utils . FileUtils Ċ import Ġcom . google . common . truth . Truth Ċ import Ġorg . junit . Before Ċ import Ġorg . junit . Rule Ċ import Ġorg . junit . Test Ċ import Ġorg . junit . rules . Temporary Folder Ċ import Ġjava . io . File Ċ import Ġjava . nio . file . Files Ċ import Ġjava . nio . file . Path Ċ import Ġjava . util . zip . Zip Entry Ċ import Ġjava . util . zip . Zip OutputStream Ċ import Ġkotlin . streams . toList Ċ Ċ /** Ċ Ġ* ĠTesting Ġthe Ġbasic Ġscenarios Ġfor ĠDex Splitter Task . Ċ Ġ*/ Ċ class ĠDex Splitter Task Test Ġ{ ĊĠĠĠ Ġ@ get : ĠRule ĊĠĠĠ Ġval Ġtmp : ĠTemporary Folder Ġ= ĠTemporary Folder () ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġsh run k Dex Dir : ĠFile ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġdex Splitter Base Output Dir : ĠFile ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġdex Splitter Feature Output Dir : ĠFile ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġbase Classes : ĠFile ĊĠĠĠ Ġprivate Ġlateinit Ġvar Ġfeature Classes : ĠFile ĊĊĠĠĠ Ġ@ Before ĊĠĠĠ Ġfun ĠsetUp () Ġ{ ĊĠĠĠĠĠĠĠ Ġsh run k Dex Dir Ġ= Ġtmp . new Folder (" sh run k Dex ") ĊĠĠĠĠĠĠĠ Ġdex Splitter Base Output Dir Ġ= Ġtmp . new Folder () ĊĠĠĠĠĠĠĠ Ġdex Splitter Feature Output Dir Ġ= Ġtmp . new Folder () ĊĊĠĠĠĠĠĠĠ Ġbase Classes Ġ= ĠFile ( tmp . root , Ġ" base / base . jar ") ĊĠĠĠĠĠĠĠ ĠFileUtils . mkdir s ( base Classes . parent File ) ĊĠĠĠĠĠĠĠ ĠTest Inputs Generator . jar With Empty Classes ( base Classes . to Path (), ĠlistOf (" base / A ", Ġ" base / B ")) ĊĊĊĠĠĠĠĠĠĠ Ġfeature Classes Ġ= ĠFile ( tmp . root , Ġ" feature - foo . jar ") ĊĠĠĠĠĠĠĠ ĠFileUtils . mkdir s ( feature Classes . parent File ) ĊĠĠĠĠĠĠĠ ĠTest Inputs Generator . jar With Empty Classes ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfeature Classes . to Path (), ĠlistOf (" feature / A ", Ġ" feature / B ")) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Basic () Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠWe Ġrun ĠR 8 Ġfirst Ġto Ġgenerate Ġdex Ġfile Ġfrom Ġjar Ġfiles . ĊĠĠĠĠĠĠĠ Ġrun R 8 ( listOf ( base Classes , Ġfeature Classes ), Ġ" class Ġ** ") ĊĊĠĠĠĠĠĠĠ Ġ// ĠCheck Ġthat Ġr 8 Ġran Ġas Ġexpected Ġbefore Ġrunning Ġdex Splitter ĊĠĠĠĠĠĠĠ Ġval Ġr 8 Dex Ġ= Ġget Dex ( sh run k Dex Dir . to Path ()) ĊĠĠĠĠĠĠĠ ĠassertThat ( r 8 Dex ). contains Classes ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" L base / A ;", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" L base / B ;", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" L feature / A ;", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" L feature / B ; ") ĊĊĠĠĠĠĠĠĠ Ġrun Dex Splitter ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsh run k Dex Dir , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġset Of ( feature Classes ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbase Classes ) ĊĊĠĠĠĠĠĠĠ Ġcheck Dex Splitter Outputs () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Non Ex istent Mapping File () Ġ{ ĊĊĠĠĠĠĠĠĠ Ġ// ĠWe Ġrun ĠR 8 Ġfirst Ġto Ġgenerate Ġdex Ġfile Ġfrom Ġjar Ġfiles . ĊĠĠĠĠĠĠĠ Ġrun R 8 ( listOf ( base Classes , Ġfeature Classes ), Ġ" class Ġ** ") ĊĊĠĠĠĠĠĠĠ Ġ// ĠCheck Ġthat Ġr 8 Ġran Ġas Ġexpected Ġbefore Ġrunning Ġdex Splitter ĊĠĠĠĠĠĠĠ Ġval Ġr 8 Dex Ġ= Ġget Dex ( sh run k Dex Dir . to Path ()) ĊĠĠĠĠĠĠĠ ĠassertThat ( r 8 Dex ). contains Classes ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" L base / A ;", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" L base / B ;", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" L feature / A ;", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" L feature / B ; ") ĊĊĠĠĠĠĠĠĠ Ġrun Dex Splitter ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsh run k Dex Dir , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġset Of ( feature Classes ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbase Classes , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠFile ("/ path / to / now here ")) ĊĊĠĠĠĠĠĠĠ Ġcheck Dex Splitter Outputs () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test ĊĠĠĠ Ġfun Ġtest Main Dex List File () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġnum Classes Ġ= Ġ 0 xFFFF / 3 Ġ+ Ġ 1 ĊĠĠĠĠĠĠĠ Ġval Ġbase Split Ġ= Ġtmp . root . resolve (" base - split . jar "). also Ġ{ Ġfile Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ ĠZip OutputStream ( file . output Stream ()). use Ġ{ Ġzip Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrepeat ( num Classes ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġzip . put Next Entry ( Zip Entry (" test / A $ it . class ")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġempty Class Ġ= ĠTest Classes Generator . class With Empty Methods ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" A $ it ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" foo : () V ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" foo 2 : () V ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġzip . write ( empty Class ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġzip . close Entry () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġrun R 8 ( listOf ( base Split , Ġfeature Classes ), Ġ" class Ġ** Ġ{ Ġ* ; Ġ} ") ĊĊĠĠĠĠĠĠĠ Ġval Ġprimary Dex Ġ= ĠlistOf (" test / A 0 ", Ġ" test / A 1 ", Ġ" test / A ${ num Classes Ġ- Ġ 1 }") ĊĠĠĠĠĠĠĠ Ġval Ġprimary Classes Ġ= Ġtmp . new File (" main Dex List . txt "). also Ġ{ Ġfile Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfile . write Text ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprimary Dex . join ToString ( separator Ġ= ĠSystem . line Separator ()) Ġ{ Ġ"$ it . class " Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġrun Dex Splitter ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsh run k Dex Dir , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġset Of ( feature Classes ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbase Split , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmapping File Src Ġ= Ġnull , ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġmain Dex List Ġ= Ġprimary Classes ) ĊĊĠĠĠĠĠĠĠ ĠassertThat Dex ( dex Splitter Base Output Dir . resolve (" classes . dex ")). contains Classes In ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprimary Dex . map Ġ{ Ġ" L $ it ;" Ġ} ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġrun Dex Splitter ( ĊĠĠĠĠĠĠĠ Ġdex Dir : ĠFile , ĊĠĠĠĠĠĠĠ Ġfeature J ars : ĠSet < File >, ĊĠĠĠĠĠĠĠ Ġbase Jar : ĠFile , ĊĠĠĠĠĠĠĠ Ġmapping File Src : ĠFile ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠ Ġmain Dex List : ĠFile ? Ġ= Ġnull ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ ĠDex Splitter Task . split Dex ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfeature J ars Ġ= Ġfeature J ars , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbase Jar Ġ= Ġbase Jar , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmapping File Src Ġ= Ġmapping File Src , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmain Dex List Ġ= Ġmain Dex List , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfeature Dex Dir Ġ= Ġdex Splitter Feature Output Dir , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbase Dex Dir Ġ= Ġ Ġdex Splitter Base Output Dir , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinput Dirs Ġ= ĠlistOf ( dex Dir ) ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġrun R 8 ( j ars : ĠList < File >, Ġr 8 Keep : ĠString ? Ġ= Ġnull ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġval Ġpro guard Configurations : ĠMutable List < String > Ġ= Ġmutable ListOf ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ"- ignore warnings ") ĊĊĠĠĠĠĠĠĠ Ġr 8 Keep ?. let Ġ{ Ġpro guard Configurations . add ("- keep Ġ$ it ") Ġ} ĊĊĠĠĠĠĠĠĠ ĠR 8 Task . shrink ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġboot Classpath Ġ= ĠlistOf ( TestUtils . resolve Platform Path (" android . jar "). to File ()), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmin Sdk Version Ġ= Ġ 2 1 , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Debug gable Ġ= Ġtrue , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġenable Des ug aring Ġ= Ġfalse , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdisable Tree Sh aking Ġ= Ġfalse , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdisable Min ification Ġ= Ġtrue , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmain Dex List Files Ġ= ĠlistOf (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmain Dex Rules Files Ġ= ĠlistOf (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinput Pro guard Mapping Ġ= Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpro guard Configuration Files Ġ= ĠlistOf (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpro guard Configurations Ġ= Ġpro guard Configurations , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvariant Type Ġ= ĠVariant Type Impl . BASE _ AP K , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmessage Receiver Ġ= ĠNo Op Message Receiver (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġde xing Type Ġ= ĠDex ing Type . NATIVE _ MULT ID EX , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġuse Full R 8 Ġ= Ġfalse , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreferenced Inputs Ġ= ĠlistOf (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclasses Ġ= Ġj ars , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġresources Ġ= Ġj ars , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpro guard Output Files Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPro guard Output Files ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtmp . new File (" mapping . txt "). to Path (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtmp . new File (" seeds . txt "). to Path (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtmp . new File (" usage . txt "). to Path (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtmp . new File (" configuration . txt "). to Path (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtmp . new File (" missing _ rules . txt "). to Path (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoutput Ġ= Ġsh run k Dex Dir , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoutput Resources Ġ= Ġtmp . new File (" sh run k Resources . jar "), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmain Dex List Output Ġ= Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfeature Class J ars Ġ= ĠlistOf (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfeature Java Resource J ars Ġ= ĠlistOf (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfeature Dex Dir Ġ= Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfeature Java Resource Output Dir Ġ= Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlib Configuration Ġ= Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoutput Keep Rules Dir Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcheck Dex Splitter Outputs () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbase Dex Ġ= Ġget Dex ( dex Splitter Base Output Dir . to Path ()) ĊĠĠĠĠĠĠĠ ĠassertThat ( base Dex ). contains Classes (" L base / A ;", Ġ" L base / B ; ") ĊĠĠĠĠĠĠĠ ĠassertThat ( base Dex ). does Not Contain Classes (" L feature / A ;", Ġ" L feature / B ; ") ĊĊĠĠĠĠĠĠĠ Ġval Ġfeature Dex Ġ= Ġget Dex ( File ( dex Splitter Feature Output Dir , Ġ" feature - foo "). to Path ()) ĊĠĠĠĠĠĠĠ ĠassertThat ( feature Dex ). contains Classes (" L feature / A ;", Ġ" L feature / B ; ") ĊĠĠĠĠĠĠĠ ĠassertThat ( feature Dex ). does Not Contain Classes (" L base / A ;", Ġ" L base / B ; ") ĊĊĠĠĠĠĠĠĠ ĠTr uth . assertThat ( dex Splitter Feature Output Dir . list Files (). map Ġ{ it . name } Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. does Not Contain (" base ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġget Dex ( path : ĠPath ): ĠDex Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġdex Files Ġ= ĠFiles . walk ( path ). filter Ġ{ Ġit . toString (). endsWith (". dex ") Ġ}. toList () ĊĠĠĠĠĠĠĠ Ġreturn ĠDex ( dex Files . single ()) ĊĠĠĠ Ġ} Ċ } Ċ