// ĠCopyright Ġ 2 0 2 1 ĠGoogle ĠLLC Ċ // Ċ // Ġ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 . google . android . libraries . car . trust agent . ble message stream . version 2 Ċ Ċ import Ġcom . google . android . comp anion protos . Device Message Proto . Message Ċ import Ġcom . google . android . comp anion protos . Packet Proto . Packet Ċ import Ġcom . google . android . libraries . car . trust agent . util . lo ge Ċ import Ġcom . google . android . libraries . car . trust agent . util . log w Ċ import Ġcom . google . android . libraries . car . trust agent . util . to HexString Ċ import Ġjava . io . ByteArray OutputStream Ċ import Ġjava . io . IOException Ċ Ċ /** Ċ Ġ* ĠMan ages Ġincoming Ġ[ Packet ] s Ġby Ġgrouping Ġthem Ġby Ġ[ Packet . getMessage Id ] Ġand Ġnotify ing Ċ Ġ* Ġregistered Ġlistener Ġwhen Ġa Ġcomplete Ġmessage Ġhas Ġbeen Ġreceived . Ċ Ġ*/ Ċ class ĠPacket Payload Stream Ġ{ ĊĠ Ġ/** ĠA Ġmap Ġof Ġmessage ĠIDs Ġto Ġdata Ġthat Ġare Ġwaiting Ġto Ġbe Ġformed Ġinto Ġcomplete Ġmessages . Ġ*/ ĊĠ Ġprivate Ġval Ġpending Data Ġ= Ġmutable Map Of < Int , ĠPending Message >() ĊĊĠ Ġvar Ġlistener : ĠOn Message Completed Listener ? Ġ= Ġnull ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠWrites Ġthe Ġgiven Ġ[ packet ] Ġinto Ġmessage - id - based Ġstream . ĊĠĠ Ġ* ĊĠĠ Ġ* ĠIf Ġthe Ġwrite Ġcannot Ġbe Ġcompleted , Ġan Ġ[ IOException ] Ġwill Ġbe Ġthrown . ĊĠĠ Ġ* ĊĠĠ Ġ* ĠAn Ġ[ IllegalStateException ] Ġcan Ġalso Ġbe Ġthrown Ġif Ġthere Ġis Ġin consistency Ġwith Ġthe Ġpacket Ġthat Ġis ĊĠĠ Ġ* Ġbeing Ġwritten Ġ( e . g . Ġif Ġthe Ġgiven Ġ` packet ` Ġis Ġ Ġwritten Ġout - of - order Ġwith Ġthe Ġlast Ġwrite Ġof Ġa ĊĠĠ Ġ* Ġ` packet ` Ġwith Ġthe Ġsame Ġmessage Ġid ). ĠWhen Ġthis Ġhappens , Ġthe Ġstream Ġshould Ġnot Ġbe Ġreused . ĊĠĠ Ġ*/ ĊĠ Ġfun Ġwrite ( packet : ĠPacket ) Ġ{ ĊĠĠĠ Ġval ĠmessageId Ġ= Ġpacket . message Id ĊĠĠĠ Ġvar Ġpending Message Ġ= Ġpending Data . get ( message Id )?. apply Ġ{ ĊĠĠĠĠĠ Ġif Ġ(! should Process Packet ( packet , Ġcurrent Pending Message Ġ= Ġthis )) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn @ write ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ Ġwrite ( packet ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġif Ġ( pending Message Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠ Ġ// ĠThe Ġfirst Ġmessage Ġmust Ġstart Ġat Ġ 1 , Ġbut Ġhandle Ġreceiving Ġthe Ġlast Ġpacket Ġas Ġthis Ġcould ĊĠĠĠĠĠ Ġ// Ġrepresent Ġa Ġduplicate Ġpacket . ĠAll Ġother Ġcases Ġwill Ġtrigger Ġan Ġexception Ġwhen Ġthe Ġpacket ĊĠĠĠĠĠ Ġ// Ġis Ġparsed Ġinto Ġa ĠB le Device Message . ĊĠĠĠĠĠ Ġif Ġ( packet . packet Number Ġ!= Ġ 1 Ġ&& Ġpacket . packet Number Ġ== Ġpacket . total Packets ) Ġ{ ĊĠĠĠĠĠĠĠ Ġlog w ( ĊĠĠĠĠĠĠĠĠĠ ĠTAG , ĊĠĠĠĠĠĠĠĠĠ Ġ" Received Ġa Ġfirst Ġmessage Ġthat Ġis Ġnot Ġthe Ġstart Ġof Ġa Ġpacket . ĠIgn oring ." ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠ Ġpending Message Ġ= Ġpacket . to Pending Message () ĊĠĠĠĠĠ Ġpending Data [ message Id ] Ġ= Ġpending Message ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġif Ġ( packet . packet Number Ġ!= Ġpacket . total Packets ) Ġ{ ĊĠĠĠĠĠ Ġreturn ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġble Device Message Ġ= Ġtry Ġ{ ĊĠĠĠĠĠ ĠMessage . parseFrom ( pending Message . message Stream . toByteArray ()) ĊĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠ Ġlo ge ( TAG , Ġ" Could Ġnot Ġparse ĠB le Packets Ġwith Ġmessage Ġid Ġ$ message Id Ġas ĠB le Device Message .") ĊĠĠĠĠĠ Ġthrow Ġe ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġpending Data . remove ( message Id ) ĊĠĠĠ Ġlistener ?. on Message Completed ( ble Device Message ) ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠValid ates Ġthe Ġgiven Ġ[ packet ]' s Ġmetadata Ġand Ġreturns Ġ` true ` Ġif Ġthe Ġ[ packet ] Ġis Ġvalid Ġfor Ġbeing ĊĠĠ Ġ* Ġwritten Ġinto Ġthe Ġmessage Ġstream . ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġfun Ġshould Process Packet ( ĊĠĠĠ Ġpacket : ĠPacket , ĊĠĠĠ Ġcurrent Pending Message : ĠPending Message ĊĠ Ġ): ĠBoolean Ġ{ ĊĠĠĠ Ġif Ġ( current Pending Message . last Packet Number Ġ+ Ġ 1 Ġ== Ġpacket . packet Number ) Ġ{ ĊĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠA Ġduplicate Ġpacket Ġcan Ġjust Ġbe Ġignored , Ġwhile Ġan Ġout - of - order Ġpacket Ġrepresents Ġthat Ġthe ĊĠĠĠ Ġ// Ġstream Ġshould Ġbe Ġclosed . ĊĠĠĠ Ġif Ġ( current Pending Message . last Packet Number Ġ== Ġpacket . packet Number ) Ġ{ ĊĠĠĠĠĠ Ġlog w ( ĊĠĠĠĠĠĠĠ ĠTAG , ĊĠĠĠĠĠĠĠ Ġ" Received Ġa Ġduplicate Ġpacket Ġ(${ packet . packet Number }) Ġfor Ġmessage Ġ${ packet . message Id }. Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠ Ġ" Ign oring ." ĊĠĠĠĠĠ Ġ) ĊĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġthrow ĠIllegalStateException ( ĊĠĠĠĠĠ Ġ" Received Ġout - of - order Ġpacket Ġ${ packet . packet Number }. Ġ" Ġ+ ĊĠĠĠĠĠĠĠ Ġ" Expecting Ġ${ current Pending Message . last Packet Number Ġ+ Ġ 1 }" ĊĠĠĠ Ġ) ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun ĠPacket . to Pending Message (): ĠPending Message Ġ{ ĊĠĠĠ Ġval Ġpayload Bytes Ġ= Ġpayload . toByteArray () ĊĠĠĠ Ġval Ġmessage Stream Ġ= ĠByteArrayOutputStream ( payload Bytes . size ). apply Ġ{ Ġwrite ( payload Bytes ) Ġ} ĊĊĠĠĠ Ġreturn ĠPending Message ( message Stream , Ġlast Packet Number Ġ= Ġpacket Number ) ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠInv oked Ġwhen Ġ[ B le Packet ] s Ġthrough Ġ[ write ] Ġcan Ġbe Ġcombined Ġinto Ġa Ġ[ B le Device Message ]. ĊĠĠ Ġ*/ ĊĠ Ġinterface ĠOn Message Completed Listener Ġ{ ĊĠĠĠ Ġfun Ġon Message Completed ( device Message : ĠMessage ) ĊĠ Ġ} ĊĊĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠ Ġprivate Ġconst Ġval ĠTAG Ġ= Ġ" Packet Payload Stream " ĊĠ Ġ} Ċ } Ċ Ċ private Ġdata Ġclass ĠPending Message ( ĊĠ Ġvar Ġmessage Stream : ĠByteArrayOutputStream , ĊĠ Ġvar Ġlast Packet Number : ĠInt Ċ ) Ġ{ ĊĠ Ġ/** ĊĠĠ Ġ* ĠWrites Ġthe Ġ` payload ` Ġand Ġ` packet Number ` Ġfrom Ġthe Ġgiven Ġ[ packet ] Ġto Ġthis Ġ` Pending Message `. ĊĠĠ Ġ* ĊĠĠ Ġ* ĠThe Ġ` payload ` Ġis Ġappended Ġto Ġthe Ġend Ġof Ġ` message Stream `. ĠIf Ġthis Ġwrite Ġencounter s Ġan Ġerror , ĊĠĠ Ġ* Ġthen Ġan Ġ[ IOException ] Ġis Ġthrown . ĊĠĠ Ġ*/ ĊĠ Ġfun Ġwrite ( packet : ĠPacket ) Ġ{ ĊĠĠĠ Ġmessage Stream . write ( packet . payload . toByteArray ()) ĊĠĠĠ Ġlast Packet Number Ġ= Ġpacket . packet Number ĊĠ Ġ} ĊĊĠ Ġ/** ĠReturns Ġa Ġhex Ġrepresentation Ġof Ġ[ message Stream ]. Ġ*/ ĊĠ Ġfun Ġmessage Stream To Hex (): ĠString Ġ= Ġmessage Stream . toByteArray (). to HexString () Ċ } Ċ