<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>victor&apos;s hacker blog</title>
    <description>meu blog sobre aprendizados relacionados a tecnologia, desenvolvimento e segurança.
</description>
    <link>https://blog.victorlpgazolli.dev/</link>
    <atom:link href="https://blog.victorlpgazolli.dev/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sun, 10 May 2026 22:45:21 +0000</pubDate>
    <lastBuildDate>Sun, 10 May 2026 22:45:21 +0000</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>
    
      <item>
        <title>Como transformei minha Alexa em um auto-falante inteligente para meu Mac</title>
        <description>&lt;p&gt;&lt;img src=&quot;../_assets/Ia_generated_alexa_playing_music.png&quot; alt=&quot;Banner alexa tocando musica do pc&quot; /&gt;&lt;/p&gt;

&lt;p&gt;No começo desse ano eu percebi o quão distante as Alexas estão ficando em relação ao avanço tecnologico das IAs. Se você não paga subscription os auto-falantes que um dia chamamos de “inteligentes” estão ficando literalmente “burros” a cada dia que passa.&lt;/p&gt;

&lt;p&gt;há uns 4 anos atrás eu ganhei uma &lt;a href=&quot;https://www.amazon.com.br/Echo-Show-5-3%C2%AAgera%C3%A7%C3%A3o-Cor-Preta/dp/B09B2TSNNN&quot;&gt;Echo Show 5&lt;/a&gt; de um amigo e desde então eu tenho usado ela diariamente para controlar algumas coisas aqui em casa, tocar músicas e também para tirar duvidas aleatórias do dia a dia.&lt;/p&gt;

&lt;p&gt;Decidi que ja está na hora de aposentar a Echo e dar espaço para uma próxima assistente virtual.&lt;/p&gt;

&lt;p&gt;Uma foto da minha alexa ainda no ritmo natalino:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/alexa_noel.jpeg&quot; alt=&quot;Alexa noel&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ao invés de simplesmente vender a echo show eu decidi fazer algo útil com ela.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;se a Echo não é tão boa sendo uma uma assistente virtual, então o que ela é boa fazendo?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Eu sei que ela é boa tocando música, os speakers dela são muito bons (talvez até melhor do que o meu PC).&lt;/p&gt;

&lt;p&gt;Fora que um speaker para computador que tenha tela touch embutida e que sejam relativamente baratas é raro de se ver.&lt;/p&gt;

&lt;p&gt;E dai que veio a ideia de transformar ela em um speaker inteligente pro meu computador. Um projeto que me diverti fazendo, portanto vou compartilhar com vocês os desafios que tive e como resolvi.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;procurando-formas-de-usar-a-echo-como-speaker&quot;&gt;Procurando formas de usar a Echo como speaker&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Por onde começar nesse projeto de conectar a alexa no meu PC para reproduzir o som?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A resposta mais obvia é simplesmente usar o Spotify que ja vem nativamente. Mas tem um problema nisso: um speaker de verdade não é seletivo, o som vem do PC como um todo e não apenas de um aplicativo.&lt;/p&gt;

&lt;p&gt;Será que existe alguma skill no app da alexa que dê para adicionar para isso? bom, eu não encontrei. Depois de muitas pesquisas não achei nenhuma forma oficial de usar como um speaker como eu gostaria.&lt;/p&gt;

&lt;p&gt;O único caminho que me restou foi procurar alternativas na conunidade que desse para customizar a alexa a ponto de transformar ela em um speaker…&lt;/p&gt;

&lt;p&gt;Tive sorte em encontrar que 1 mês antes &lt;a href=&quot;https://xdaforums.com/t/rom-unofficial-11-cronos-lineageos-18-1-for-the-amazon-echo-show-5-2021.4772598/&quot;&gt;no Forum XDA&lt;/a&gt; postaram uma forma de “desbloquear” alguns modelos da Echo Show dando possibilidade de instalar seu próprio sistema operacional.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/amaze-amazed.gif&quot; alt=&quot;Alexa noel&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Esse post abriu meus olhos no que a Echo é capaz, ela conseguir rodar Android é incrivel e significa que esse plano (de usar ela como um speaker) tecnicamente é possível.&lt;/p&gt;

&lt;p&gt;Apesar de possível, desbloquear o bootloader da Echo Show não é uma tarefa fácil e sem riscos. Se algo der errado você pode simplemente quebrar sua alexa num ponto irrecuperavel.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;instalando-android-na-echo-show&quot;&gt;Instalando Android na Echo Show&lt;/h2&gt;

&lt;p&gt;Como minha Echo Show 5 é da segunda geração eu precisei seguir esse &lt;a href=&quot;https://xdaforums.com/t/unlock-root-twrp-unbrick-amazon-echo-show-5-2nd-gen-2021-cronos.4772596/&quot;&gt;passo a passo aqui&lt;/a&gt;, la tem todos os links necessários. Caso tenha curiosidade o repositório com o exploit chain é &lt;a href=&quot;https://github.com/R0rt1z2/amonet&quot;&gt;R0rt1z2/amonet&lt;/a&gt;, juntaram eles em 1 pacote só para que o processo seja facilitado.&lt;/p&gt;

&lt;p&gt;Antes de começar a seguir o passo a passo eu li todas as mensagens do &lt;a href=&quot;https://xdaforums.com/t/unlock-root-twrp-unbrick-amazon-echo-show-5-2nd-gen-2021-cronos.4772596/&quot;&gt;post original&lt;/a&gt;, vi muitos tutoriais diferentes para entender a fundo o que acontece e o que deve ser feito, se for fazer isso sugiro fazer o mesmo.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/amonet_rodando_na_alexa.jpeg&quot; alt=&quot;Amonet rodando na echo show 5&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Tinha uma pequena chance desse script quebrar minha alexa, então os 5 minutos dele rodando pareceram 30 minutos. Fiquei literalmente assim:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/kermit_tense_moment.gif&quot; alt=&quot;rodando script tenso meme&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;deu-bom&quot;&gt;Deu bom!&lt;/h3&gt;

&lt;p&gt;Confesso que ver a tela de configuração do &lt;a href=&quot;https://twrp.me/about/&quot;&gt;TWRP&lt;/a&gt; deu um alívio.&lt;/p&gt;

&lt;p&gt;Com a Echo desbloqueada eu poderia substituir o SO pelo o que eu quisesse, mas seria loucura fazer isso sem backup dos arquivos importantes da sua alexa, melhor prevenir fazendo backup do SO antigo:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/alexa_rodando_twrp.jpeg&quot; alt=&quot;TWRP fazendo backup&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Agora que eu tenho backup posso ficar tranquilo caso faça alguma coisa de errado.&lt;/p&gt;

&lt;p&gt;Conforme o post eu instalei o &lt;a href=&quot;https://lineageos.org/&quot;&gt;LineageOS 18&lt;/a&gt; diretamente pelo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TWRP&lt;/code&gt; mesmo.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/alexa_com_lineage_os_18.jpeg&quot; alt=&quot;lineage OS instalado&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;sucesso-&quot;&gt;Sucesso !&lt;/h3&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;em-busca-de-uma-solução-p-redirecionar-áudio&quot;&gt;Em busca de uma solução p/ redirecionar áudio&lt;/h2&gt;

&lt;p&gt;Apesar da Echo estar rodando um SO Android eu ainda tinha um caminho pela frente até ela virar um Speaker de verdade.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/almost_there_meme.png&quot; alt=&quot;project almost ready meme&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Eu ainda precisava alguma forma de “espelhar” ou redirecionar o audio do meu PC, e para isso tive que pesquisar bastante sobre o assunto e nesse processo descobri várias formas diferentes de fazer isso:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Nome&lt;/th&gt;
      &lt;th&gt;É software pago?&lt;/th&gt;
      &lt;th&gt;Artefatos p/ baixar&lt;/th&gt;
      &lt;th&gt;Método&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;http://www.videolan.org/vlc/&quot;&gt;VLC&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;é gratis!&lt;/td&gt;
      &lt;td&gt;Linux/Mac/Windows -&amp;gt; iOS/Android&lt;/td&gt;
      &lt;td&gt;WIFI&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/BreadFish64/AndroidUsbAudioDevice&quot;&gt;AndroidUsbAudioDevice&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;é Grátis!&lt;/td&gt;
      &lt;td&gt;Windows -&amp;gt; Android&lt;/td&gt;
      &lt;td&gt;USB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://audiorelay.net/&quot;&gt;audiorelay&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Grátis com anúncios!&lt;/td&gt;
      &lt;td&gt;Linux/Mac/Windows -&amp;gt; Android&lt;/td&gt;
      &lt;td&gt;WIFI/USB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://georgielabs.net/&quot;&gt;SoundWire Server&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Grátis com anúncios!&lt;/td&gt;
      &lt;td&gt;Linux/Windows -&amp;gt; Android&lt;/td&gt;
      &lt;td&gt;WIFI&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://rogueamoeba.com/airfoil/&quot;&gt;Airfoil&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Pago!&lt;/td&gt;
      &lt;td&gt;Mac -&amp;gt; iOS/Android&lt;/td&gt;
      &lt;td&gt;WIFI&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;No meu caso eu precisava de um programa que suportase &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mac -&amp;gt; Android&lt;/code&gt; e de preferência algo 100% via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USB&lt;/code&gt;, grátis e opensource.&lt;/p&gt;

&lt;p&gt;A solução do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;audiorelay&lt;/code&gt; é o que chega mais próximos ao que eu preciso out-of-the-box, o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VLC&lt;/code&gt; me atenderia caso eu rodasse comandos no terminal para redirecionar o uso do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WIFI&lt;/code&gt; para o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USB&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Eu percebi que todas as opções exigiam instalar algo no computador (obviamente) mas também algo no meu Android.&lt;/p&gt;

&lt;p&gt;Eu até tolero baixar um app no android da echo, mas eu quero evitar com todas as forças a parte burocrática:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;configurar, abrir o app no celular e no computador, rodar comandos toda vez, tudo isso só pra fazer o áudio ir pro celular.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;descartei &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;audiorelay&lt;/code&gt; por ter anúncios e &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VLC&lt;/code&gt; eu descartei por ter vários passos a serem feitos pra usar, não é plug-and-play como eu gostaria.&lt;/p&gt;

&lt;p&gt;E todas as outras que encontrei não atendiam algum dos requisitos, sempre tinham pelo menos um ponto negativo.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/bad_choinces_meme.jpg&quot; alt=&quot;bad choices meme&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Veja, as soluções em si não chegam a ser ruins, eu estava buscando algo bem específico e nesse contexto não eram opções boas.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;desistindo-e-criando-minha-própria-solução&quot;&gt;Desistindo e criando minha própria solução&lt;/h2&gt;

&lt;p&gt;A experiência ideal é rodar apenas 1 comando no computador e tudo se resolver sozinho.&lt;/p&gt;

&lt;p&gt;Esse é um dos principais motivos de eu ser fã do &lt;a href=&quot;https://github.com/Genymobile/scrcpy&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scrcpy&lt;/code&gt;&lt;/a&gt; e &lt;a href=&quot;https://github.com/Genymobile/gnirehtet&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gnirehtet&lt;/code&gt;&lt;/a&gt;, ambos tem uma experiência de uso muito simples mesmo fazendo várias coisas complexas por baixo dos panos.&lt;/p&gt;

&lt;p&gt;O &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scrcpy&lt;/code&gt; redireciona áudio do celular para o PC, portanto de curioso resolvi olhar se nele tinha como fazer o caminho oposto. Recebi um banho de agua fria: o principal mantenedor &lt;a href=&quot;https://github.com/Genymobile/scrcpy/issues/790#issuecomment-953351751&quot;&gt;disse que isso é fora do escopo do scrcpy&lt;/a&gt; e faz sentido.&lt;/p&gt;

&lt;p&gt;Pelo comentário dele, deu a entender que não é viável tecnicamente redirecionar áudio do PC para celular: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;no technical solution anyway&quot;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/are_you_challenging_me.gif&quot; alt=&quot;meme are you challenging me&quot; /&gt;&lt;/p&gt;

&lt;p&gt;E foi nesse exato momento que decidi criar eu mesmo alguma solução.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;plano-de-implementação&quot;&gt;Plano de implementação&lt;/h2&gt;

&lt;p&gt;Objetivo: ter uma CLI que rodo 1 vez e já faz tudo acontecer, sem config e tudo &lt;em&gt;automágico&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Pré-requisitos:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;simples de usar&lt;/li&gt;
  &lt;li&gt;ser grátis e opensource&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USB&lt;/code&gt; como meio de transporte de dados&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Desisti da ideia de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WIFI&lt;/code&gt; pois tive a impressão que poderia aumentar muito a latência do áudio.&lt;/p&gt;

&lt;p&gt;Então uma visão geral do projeto e caminho dos dados seria tipo assim:&lt;/p&gt;
&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                   (1)   Interface de audio do PC       
                                    │               
                                    ▼               
                (2)   programa rodando no computador
                                    │               
                                    ▼               
                                   usb              
                                    │               
                                    ▼               
                        (3)   meu aplicativo        
                                    │               
                                    ▼               
                        (4)  audio do celular       
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Quebrei o problema maior em 4 problemas menores para facilitar.&lt;/p&gt;

&lt;p&gt;Esses mesmos “4 problemas menores” iriam tomar entre 1 a 2 semanas (nos horarios livres) de desenvolvimento para finalizar, tudo pra não gastar 1 minuto configurando algo toda vez que for usar kkkkk Mas quem nunca fez isso atire a primeira pedra.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/automate_meme.jpg&quot; alt=&quot;automation meme&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;passo-1-coleta-do-áudio-do-pc&quot;&gt;Passo 1: coleta do áudio do PC&lt;/h3&gt;

&lt;p&gt;essa foi relativamente simples… Como meu objetivo é suportar mac e linux eu foquei em usar alguma ferramenta que funcionasse bem para os 2. 
Testei algumas mas a que mais saiu melhor foi um binário chamado &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SoX (Sound eXchange)&lt;/code&gt;, eu pude escolher uma interface e trazer o dado bruto via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STDOUT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Fazendo vários testes eu consegui chegar a esse comando aqui, ele me traz exatamente o que eu preciso num sample rate e buffer definido.&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
sox &lt;span class=&quot;nt&quot;&gt;--buffer&lt;/span&gt; 3840 &lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;                &lt;span class=&quot;c&quot;&gt;# valor calculado&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; coreaudio &lt;span class=&quot;s2&quot;&gt;&quot;BlackHole 2ch&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# interface virtual&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; 48000 &lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;                     &lt;span class=&quot;c&quot;&gt;# 48 kHz&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; 2 &lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;                         &lt;span class=&quot;c&quot;&gt;# 2 canais de áudio&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; 16 &lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;                        &lt;span class=&quot;c&quot;&gt;# 16-bit PCM&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; signed-integer &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;         &lt;span class=&quot;c&quot;&gt;# little-endian Signed Int&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; raw - 2&amp;gt;/dev/null            &lt;span class=&quot;c&quot;&gt;# output sem inferir formato de áudio&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;coleta do audio de interface de áudio do pc ✅&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;passo-2-escrita-de-dados-em-um-device-usb&quot;&gt;Passo 2: escrita de dados em um device USB&lt;/h3&gt;

&lt;p&gt;Com poucas pesquisas já percebi que a melhor biblioteca para isso é a &lt;a href=&quot;https://github.com/libusb/libusb&quot;&gt;libusb&lt;/a&gt;, ela funciona com qualquer versão do USB e funciona cross-platform.&lt;/p&gt;

&lt;p&gt;O único problema dessa biblioteca é a documentação, particularmente não achei muito fácil de entender, falta exemplos para as funcionalidades.&lt;/p&gt;

&lt;p&gt;Mas de qualquer forma achei vários exemplos online usando essa lib portanto acabou que foi uma boa escolha.
No final para escrever dados na interface USB eu precisei seguir um fluxo semelhante a esse:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Abro uma conexão com um device (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libusb_open_device_with_vid_pid&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Reivindico a interface USB escolhendo o device (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libusb_claim_interface&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Inicio uma transferência passando um callback (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libusb_fill_bulk_transfer&lt;/code&gt;)
    &lt;ul&gt;
      &lt;li&gt;3.1. Callback vai inflando o buffer com os bytes conforme vão chegando&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Envio os dados para aquele device (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libusb_submit_transfer&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;envio de dados para o dispositivo via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USB&lt;/code&gt; ✅&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;passo-3-um-app-conseguir-ler-os-dados-que-vem-pelo-usb&quot;&gt;Passo 3: Um app conseguir ler os dados que vem pelo USB&lt;/h3&gt;

&lt;p&gt;Usar o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libusb&lt;/code&gt; pra escrever no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USB&lt;/code&gt; funcionou mas foi sofrido até conseguir ficar certinho como eu queria, por isso para o passo 3 eu fui atrás de soluções fáceis de usar.&lt;/p&gt;

&lt;p&gt;Durante minhas pesquisas eu esbarrei com o &lt;a href=&quot;https://source.android.com/docs/core/interaction/accessories/protocol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Android Open Accessory (AOA)&lt;/code&gt;&lt;/a&gt;, um protocolo que permite um aplicativo interagir com o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USB&lt;/code&gt; do celular de uma forma relativamente simples.&lt;/p&gt;

&lt;p&gt;Achei bem promissor, mas fiquei na dúvida se ainda funciona visto que o protocolo é de 15 anos atrás (2011).&lt;/p&gt;

&lt;p&gt;Aparentemente da pra saber se seu device suporta o “modo acessory” do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AOA&lt;/code&gt; usando o comando:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adb shell &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; /system/etc/permissions | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;usb.accessory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;E pra minha surpresa, TODOS meus devices tinham o arquivo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usb.accessory.xml&lt;/code&gt; ai na pasta (confirmando que suportam esse modo acessório), isso é muito bom!&lt;/p&gt;

&lt;p&gt;Olhando mais a fundo nesse protocolo eu encontrei 2 versões:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://source.android.com/docs/core/interaction/accessories/aoa&quot;&gt;v1.0&lt;/a&gt;: básica e tem só o essencial&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://source.android.com/docs/core/interaction/accessories/aoa2&quot;&gt;v2.0&lt;/a&gt;: adiciona mais capacidades ao protocolo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Como eu precisava só do essencial segui com a versão v1.0.&lt;/p&gt;

&lt;p&gt;Foi relativamente simples implementar, precisei declarar no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AndroidManifest&lt;/code&gt; um &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Service&lt;/code&gt; que tivesse intent filter do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USB_ACCESSORY_ATTACHED&lt;/code&gt;, passando metadados do acessório:&lt;/p&gt;
&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;usb-accessory&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;manufacturer=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Victor&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;model=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;DroidSink&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;version=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1.0&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Essa configuração é essencial para que o programa do pc consiga abrir uma conexão com meu app do celular.&lt;/p&gt;

&lt;p&gt;No momento que o usuário aceita o popup de pareamento, o &lt;a href=&quot;https://developer.android.com/reference/android/hardware/usb/UsbManager&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UsbManager&lt;/code&gt;&lt;/a&gt; nos permite conectar no device e ao fazer isso e recebemos um objeto do tipo &lt;a href=&quot;https://developer.android.com/reference/android/os/ParcelFileDescriptor.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ParcelFileDescriptor&lt;/code&gt;&lt;/a&gt;, combinando ele a um &lt;a href=&quot;https://developer.android.com/reference/kotlin/java/io/FileInputStream&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FileInputStream&lt;/code&gt;&lt;/a&gt; nos permite iniciar a leitura de forma muito simples.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;leitura de dados no app via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USB&lt;/code&gt; ✅&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;passo-4-reproduzir-o-áudio-no-aparelho&quot;&gt;Passo 4: Reproduzir o áudio no aparelho&lt;/h3&gt;

&lt;p&gt;Com uma stream de dados vindo, reproduzir em aúdio é a ultima etapa do processo. Para fazer isso com qualidade precisamos garantir que o áudio de saída tem as mesmas especificações que o de entrada la no computador.&lt;/p&gt;

&lt;p&gt;Usei a API &lt;a href=&quot;https://developer.android.com/reference/android/media/AudioTrack&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AudioTrack&lt;/code&gt;&lt;/a&gt; para fazer essa configuração.&lt;/p&gt;

&lt;p&gt;Nela posso configurar uma série de coisas, por exemplo a prioridade desse som, o tipo dele, modo de transfêrencia que será usado e por ai vai.
Para o tamanho de buffer eu fui com o mesmo valor que defini na coleta de audio do PC:&lt;/p&gt;
&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;minBufferSize&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AudioTrack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getMinBufferSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;48000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 48 kHz&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;AudioFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;CHANNEL_OUT_STEREO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;AudioFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ENCODING_PCM_16BIT&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;chunkSize&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3840&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// valor calculado, mesmo do comando do sox&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;bufferSizeInBytes&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;maxOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;minBufferSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
      &lt;span class=&quot;n&quot;&gt;chunkSize&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// buffer de 3 vezes o tamanho do chunk de leitura&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Enquanto eu estava implementando esse passo eu tive muitos problemas de áudio picado, depois de bastante troubleshooting eu entendi que caso eu tivesse alguma configuração diferente entre a coleta e a reprodução, eu teria algum tipo de problema. A causa do problema é bem obvia olhando agora, mas na hora eu jurava que buffers maiores resolveriam, mas eu estava errado.&lt;/p&gt;

&lt;p&gt;O tempo de latência é calculado se baseando nessas especificações do projeto. Por esse e outros motivos a configuração inicial (sox) e final (no android) são essenciais para uma qualidade decente de áudio.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;reprodução de áudio no aparelho ✅&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;calculando-a-latência-geral-do-projeto&quot;&gt;Calculando a latência geral do projeto&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;⚠️ Não manjo tanto assim de cálculo de latência de áudio, posso ter deixado alguma coisa pra trás, se ver algo errado me avise&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Como eu estabeleci que 1 chunk equivale a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3840 bytes&lt;/code&gt; a escrita iria demorar cerca de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;20ms&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por garantia eu coloquei o buffer sendo 3 vezes o tamanho de escrita, sacrifico &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;60ms&lt;/code&gt; de latência pela promeça de qualidade de áudio. Estou assumindo que a leitura da stream pelo app iria demorar uns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;10ms&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/calculating_meme.jpg&quot; alt=&quot;calculating meme&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Somando tudo até agora a latência total é de aproximadamente &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;90ms&lt;/code&gt;, mas eu preferi arredondar para cima para caso eu tenha esquecido algo.&lt;/p&gt;

&lt;p&gt;Portanto do momento de coleta do som até o momento de reproduzir, a latência final é no minimo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~100ms&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Pelos meus testes esse me pareceu ser um tempo aceitável na maioria dos casos, não é excelente mas também não é incomodo, com excessão de jogos que esse delay faz diferença.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;conclusão&quot;&gt;Conclusão&lt;/h2&gt;

&lt;p&gt;Esse projeto eu chamei de &lt;a href=&quot;https://github.com/victorlpgazolli/droidsink&quot;&gt;DroidSink&lt;/a&gt;, ele está disponivel no meu github caso queira ver como está o código.&lt;/p&gt;

&lt;p&gt;Desde a publicação da v1.0.0 (dia Feb 7) eu já usei MUITO, conforme o tempo foi passando fui fazendo algumas melhorias e correções.&lt;/p&gt;

&lt;p&gt;Pra mim ele tem funcionado de forma incrível, eu rodo 1 comando e ele ja faz TUDO pra mim:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;instala o que precisa instar no celular&lt;/li&gt;
  &lt;li&gt;configura o que precisa no device&lt;/li&gt;
  &lt;li&gt;captura audio do pc e reproduz no celular&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;droidsink run
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Veja esse exemplo tocando &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;We didn&apos;t start the fire&lt;/code&gt; no meu computador e o som saindo na minha Echo rodando android.&lt;/p&gt;

&lt;video controls=&quot;&quot;&gt;
  &lt;source src=&quot;../_assets/droidsink.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  Your browser does not support the video tag.
&lt;/video&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Usando todo esse tempo identifiquei uma série de melhorias que poderiam ser feitas, como por exemplo:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Diminuir latência para no minimo 50ms.&lt;/li&gt;
  &lt;li&gt;Disponibilizar p/ download em mais lugares.&lt;/li&gt;
  &lt;li&gt;Garantir compatibilidade “out-of-the-box” com &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;linux-arm64&lt;/code&gt; e &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;linux-x86_64&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Ter alguma UI para ser apresentada no device.&lt;/li&gt;
  &lt;li&gt;Melhorar o que é apresentado no terminal enquanto roda.&lt;/li&gt;
  &lt;li&gt;… e várias outras ideias …&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sigo trabalhando nas melhorias conforme aparece um tempinho.&lt;/p&gt;
</description>
        <pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate>
        <link>https://blog.victorlpgazolli.dev/how-i-use-my-alexa-as-a-smart-pc-speaker/</link>
        <guid isPermaLink="true">https://blog.victorlpgazolli.dev/how-i-use-my-alexa-as-a-smart-pc-speaker/</guid>
        
        
        <category>mobile,</category>
        
        <category>jailbreak</category>
        
      </item>
    
      <item>
        <title>Entender a Interoperabilidade Kotlin-Swift pode evitar que você cause bugs em produção</title>
        <description>&lt;p&gt;Interoperabilidade = A capacidade de sistemas distintos conversarem e compartilhar dados.&lt;/p&gt;

&lt;p&gt;Talvez isso seja óbvio para alguns devs mobile, mas para quem desenvolve projetos que utilizam &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kotlin Multiplatform&lt;/code&gt; e ainda não deu a devida atenção e realmente parou para ler sobre a interoperabilidade entre &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kotlin&lt;/code&gt; e &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Swift&lt;/code&gt;, esse post é minha chance de te convencer a dominar esse tema.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;No desenvolvimento com &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kotlin Multiplatform&lt;/code&gt;, dominar a &lt;a href=&quot;https://github.com/kotlin-hands-on/kotlin-swift-interopedia/&quot;&gt;interoperabilidade do Kotlin com Swift&lt;/a&gt; é uma peça chave pra não gerar problemas em produção.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tudo que vai no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;commonMain&lt;/code&gt; vale pro Android e iOS, portanto nós temos como expectativa que o código seja essencialmente a mesma coisa entre as plataformas: tenha as mesmas funções, classes e se comporte igual.&lt;/p&gt;

&lt;p&gt;Esse compartilhamento de código entre a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;commonMain&lt;/code&gt; e código &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Swift&lt;/code&gt; é totalmente transparente para nós devs, tudo que eu escrevo em um aparece “igual” no outro… e após várias iterações disso é fácil esquecer que o código do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;commonMain&lt;/code&gt; passa por uma “etapa intermediária”, onde pode sofrer mudanças para que o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Swift&lt;/code&gt; consiga entender nativamente.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;De uma forma simplista, o código que o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Swift&lt;/code&gt; vê é o produto da soma &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;commonMain&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iosMain&lt;/code&gt; + um processo de multiplas compilações, e não somente &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;commonMain&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iosMain&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esse “processo de multiplas compilações” ou essa “etapa intermediária” que eu disse foi apenas uma forma de resumir, se você tiver interesse em como isso funciona vou deixar um link que dá explicações e detalhes técnicos sobre isso:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/JetBrains/kotlin/blob/master/docs/native/compilation-model.md&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kotlin/docs/native/compilation-model.md&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quantas vezes você já fez um código que no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kotlin&lt;/code&gt; ficou belíssimo, mas quando você abriu o XCode notou que esse mesmo código tava péssimo pra usar?
Ou até mesmo tinha coisas a mais nele que você não desenvolveu? Ou coisas faltando… “Cadê os parametros default que configurei??”&lt;/p&gt;

&lt;p&gt;Vou te falar um bug que eu causei em produção por não ter conhecimento 100% de como meu código &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kotlin&lt;/code&gt; ficava para o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Swift&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Para quem não manja de swift, quando você faz qualquer código que pode gerar uma exception você é obrigado a declarar isso com uma palavra chave no código: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throws&lt;/code&gt;.
Se sua função tem essa palavra chave, quem chamar ela também é obrigado a tratar senão o projeto não compila.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;canThrowErrors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;cannotThrowErrors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Tem cenários onde você sabe que não vai gerar uma exception, como por exemplo carregar uma imagem local… Nesse caso voce ainda precisa manualmente desabilitar a propagação do erro.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;photo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try!&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;loadImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;atPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;./Resources/John Appleseed.jpg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.swift.org/swift-book/documentation/the-swift-programming-language/errorhandling/&quot;&gt;link para o restante da documentação da apple sobre isso&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Qualquer exception lançada onde não está explícito que pode gerar uma exception (ou seja, não está marcada por &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throws&lt;/code&gt;) faz com que o app feche imediatamente.
Mesmo quando ela estiver dentro de um &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do-catch&lt;/code&gt; (vulgo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try-catch&lt;/code&gt;)!!! Esse é o comportamento padrão.&lt;/p&gt;

&lt;p&gt;Eu sabia que existia uma annotation chamada &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Throws&lt;/code&gt;, mas meu pensamento era: “poxa, se eu chamo meu código que vem do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kotlin&lt;/code&gt; dentro de um try catch no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Swift&lt;/code&gt;, ele ja vai ser capturado e tratado - não tem necessidade de colocar essa annotation no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kotlin&lt;/code&gt;”.&lt;/p&gt;

&lt;p&gt;Era uma exception esperada, ela de fato poderia acontecer eventualmente e ta tudo bem, inclusive foi pensando nisso que eu coloquei o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try-catch&lt;/code&gt;. No final das contas minha função gerava essa exception em um cenário específico, e justamente por lançar uma exception que o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Swift&lt;/code&gt; entendeu como inesperada, o aplicativo encerrava pois pra ele foi um erro fatal.&lt;/p&gt;

&lt;p&gt;Você pode argumentar que eu só pensava assim pois tenho mais experiência em linguagens que o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try-catch&lt;/code&gt; pode capturar todos os erros, não pela falta de conhecimento da interoperabilidade em si. E olha, você provavelmente está certo.&lt;/p&gt;

&lt;p&gt;Mas num olhar pragmático, KMP para devs mobile que já trabalhavam na área cai EXATAMENTE nesse mesmo cenário: temos uma bagagem/conhecimentos de outras linguagens que acabamos trazendo junto, e isso de um lado é ótimo, mas se não tivermos cuidado isso pode nos sabotar (vide evidência do bug que eu causei).&lt;/p&gt;

&lt;p&gt;A realidade é que:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;as plataformas/linguagens que se beneficiam com nosso código KMP tem demandas específicas, que ao subestimadas eventualmente vão trazer dores de cabeça para devs e consequentemente para os usuários finais.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Eu poderia simplesmente sair estudando &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Swift&lt;/code&gt; e todas suas particularidades, isso certamente iria fazer diferença para esse erro que comentei mais acima do post.
Porém esse caminho apesar de funcionar acaba sendo bem ineficiente.&lt;/p&gt;

&lt;p&gt;Se meu objetivo é melhorar o conhecimento e habilitade em desenvolver códigos multiplataforma, estudar uma linguagem inteira seria o equivalente a atirar para todos os lados, eu vou acertar o alvo, mas gastarei toda minha munição no processo.&lt;/p&gt;

&lt;p&gt;Seria excelente se tivesse uma documentação ou algo que me alertasse sobre essa particularidade do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Swift&lt;/code&gt; e ainda me da uma solução? 
É ai que entra a documentação de interoperabilidade com &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Swift/ObjC&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/kotlin-hands-on/kotlin-swift-interopedia/blob/main/docs/overview/Exceptions.md&quot;&gt;Olha aqui ela dizendo exatamente sobre o problema que eu tive e como resolver ele&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se você tem interesse em evoluir as habilidades em KMP, fica como minha sugestão:
Estude a interoperabilidade entre as plataformas. Com esse conhecimento você vai saber o que deve evitar no seu código multiplataforma para não causar bugs em produção igual eu fiz.&lt;/p&gt;

</description>
        <pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://blog.victorlpgazolli.dev/kotlin-multiplatform-interoperability-with-swift-objc/</link>
        <guid isPermaLink="true">https://blog.victorlpgazolli.dev/kotlin-multiplatform-interoperability-with-swift-objc/</guid>
        
        
        <category>mobile</category>
        
      </item>
    
      <item>
        <title>Usando frida para fazer debug em apps mobile</title>
        <description>&lt;p&gt;&lt;img src=&quot;../_assets/xkcd_meme.png&quot; alt=&quot;xkcd&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;introdução&quot;&gt;Introdução&lt;/h2&gt;

&lt;p&gt;No desenvolvimento mobile somos quase que obrigados a usar alguma ferramenta de debug, só rodar o app e ver o comportamento dele muitas vezes não é o suficiente para entender que uma mudança deu bom ou não, ou até mesmo pra entender como que aquele bug sinistro está acontecendo.&lt;/p&gt;

&lt;p&gt;Existem várias ferramentas bem estabelecidas no mundo mobile, acho que todos conhecem &lt;a href=&quot;https://developer.android.com/studio&quot;&gt;android studio&lt;/a&gt; e &lt;a href=&quot;https://developer.apple.com/xcode/&quot;&gt;xcode&lt;/a&gt;. Quem desenvolveu apps usando react native talvez já ouviu falar de &lt;a href=&quot;https://github.com/facebook/flipper&quot;&gt;flipper&lt;/a&gt; ou &lt;a href=&quot;https://github.com/infinitered/reactotron&quot;&gt;reactotron&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Nesse post vamos ver uma ferramenta que talvez você nunca tenha ouvido falar, e que podemos usar para abordar o debug de problemas em aplicativos móveis de uma forma completamente diferente do tradicional.&lt;/p&gt;

&lt;p&gt;Além de falar sobre ela, vou mostrar um exemplo simples de como usei ela para resolver um problema que tive recentemente.&lt;/p&gt;

&lt;p&gt;Mas já adianto que acho improvável ela substituir outras ferramentas… A ideia aqui está longe disso, é muito mais sobre ter mais uma ferramenta no seu cinto de utilidades. Cada uma das ferramentas tem suas especialidades e seus casos de uso, e como engenheiro de software precisamos reconhecer quais ferramentas funcionam melhor para cada objetivo.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/debug_with_breakpoint.png&quot; alt=&quot;debug with breakpoint&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;contexto-sobre-ferramentas-usadas-em-appsec&quot;&gt;Contexto sobre ferramentas usadas em AppSec&lt;/h2&gt;

&lt;p&gt;No meu tempo livre as vezes eu me pego estudando sobre segurança da informação focado no mobile, pesquisando na internet mas também fazendo meus próprios testes e explorações, e isso contribuiu para ter novas ideias e perspectivas diferentes sobre aplicações android e ios.&lt;/p&gt;

&lt;p&gt;A área de segurança da informação tem várias ‘sub áreas’ (AppSec acho que pode se dizer como uma sub área, certo?), mas acho que todos que trabalham com isso devem conhecer a existência de uma ONG que tem como objetivo melhorar a segurança das aplicações através de projetos open source, a famosa &lt;a href=&quot;https://owasp.org/&quot;&gt;OWASP&lt;/a&gt; (Open Worldwide Application Security Project)&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Um parenteses aqui, devo ressaltar que a ideia dessa ONG é muito legal e talvez até meio comica se puxarmos essa ideia para desenvolvimento de software: imagine por exemplo uma iniciativa dessa só que com o objetivo de acabar com todos os bugs dos softwares? ou outra pra acabar com as breaking changes ao atualizar?? apesar de meio bizarro isso seria simplesmente maravilhoso kkkkk, cade a ong pra acabar com vendor-lock? fica ai a reflexão pra você.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/imagination.webp&quot; alt=&quot;imagination meme&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Dentro da iniciativa da &lt;a href=&quot;https://owasp.org/&quot;&gt;OWASP&lt;/a&gt; tem um sub-projeto chamado &lt;a href=&quot;https://mas.owasp.org/&quot;&gt;OWASP Mobile Application Security&lt;/a&gt; - e por se tratar de mobile vamos olhar com mais atenção.&lt;/p&gt;

&lt;p&gt;O OWASP de Mobile tem uma &lt;a href=&quot;https://mas.owasp.org/MASTG/tools/#&quot;&gt;lista com várias ferramentas open source&lt;/a&gt; para facilitar o trabalho para quem quer explorar aplicações mobile.&lt;/p&gt;

&lt;p&gt;O que eu tenho percebido é que dependendo do caso elas também podem ajudar os desenvolvedores. Vou abordar em especial a ferramenta &lt;a href=&quot;https://frida.re/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Frida&lt;/code&gt;&lt;/a&gt;, mas essas outras que listei aqui também são interessantes e valem a pena conhecer:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://mas.owasp.org/MASTG/tools/android/MASTG-TOOL-0001/#using-frida-on-android&quot;&gt;MASTG-TOOL-0001 - Frida for Android&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://mas.owasp.org/MASTG/tools/ios/MASTG-TOOL-0039/&quot;&gt;MASTG-TOOL-0039 - Frida for iOS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://mas.owasp.org/MASTG/tools/android/MASTG-TOOL-0029/&quot;&gt;MASTG-TOOL-0029 - objection for Android&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://mas.owasp.org/MASTG/tools/ios/MASTG-TOOL-0074/&quot;&gt;MASTG-TOOL-0074 - objection for iOS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://mas.owasp.org/MASTG/tools/network/MASTG-TOOL-0077/&quot;&gt;MASTG-TOOL-0077 - Burp Suite&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;capacidades-vantagens-e-desvantagens&quot;&gt;Capacidades, vantagens e desvantagens&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Okok eu entendi que essas ferramentas podem ser úteis, mas pra que exatamente?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para definir &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Frida&lt;/code&gt; em uma frase eu vou usar a que tem no site deles: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dynamic instrumentation toolkit for developers, reverse-engineers, and security researchers.&lt;/code&gt;, dai falando mais tecnicamente: frida por baixo dos panos usa um &lt;a href=&quot;https://github.com/frida/frida-gum&quot;&gt;módulo escrito em C&lt;/a&gt; que permite você injetar códigos JS durante período de execução de tal forma que é possível interagir com APIs que esse módulo provem.&lt;/p&gt;

&lt;p&gt;Vou explicar melhor como isso pode ser aplicável no dia a dia.&lt;/p&gt;

&lt;p&gt;Você talvez já deve ter pego aquele bug cabuloso onde o uso de debug foi útil e talvez até necessário, aquele cenário de concorrência entre duas funções ou senão um erro que só ocorre quando o app está em um estado muito específico.&lt;/p&gt;

&lt;p&gt;Já deve estar cansado de saber que debug em ferramentas como android studio e xcode da pra colocar breakpoints para inspecionar e alterar variáveis, mas algo muito bacana e que não vejo muitas pessoas comentando é sobre o &lt;a href=&quot;https://developer.android.com/studio/debug#watchpoints&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;watchpoints (android)&lt;/code&gt;&lt;/a&gt; onde você consegue registrar um ‘hook’ para pausar a execução do app quando uma variável específica for alterada, ou no iOS o &lt;a href=&quot;https://www.objc.io/issues/19-debugging/lldb-debugging/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;thread return&lt;/code&gt; (lldb no iOS)&lt;/a&gt; que permite você alterar o valor de retorno de uma função nativa.&lt;/p&gt;

&lt;p&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Frida&lt;/code&gt; tem as mesmas capacidades de debug que falei acima (leitura, escrita e observar uma variável), mas aborda isso de uma maneira completamente diferente, e eu acredito que é ai que podemos tirar proveito dela.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/debug_matrix_morpheus.png&quot; alt=&quot;debug matrix morpheus&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;um-exemplo-simples-de-debug-que-fiz-usando-frida&quot;&gt;Um exemplo simples de debug que fiz usando Frida&lt;/h2&gt;

&lt;p&gt;Nessa semana encontrei um bug muito esquisito que acontecia apenas em dispositivos iOS em um cenário desconhecido, a única evidência ou log que eu tive sobre isso é o código do erro e uma mensagem muito superficial: &lt;a href=&quot;https://www.osstatus.com/search/results?platform=all&amp;amp;framework=Security&amp;amp;search=25291&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-25291 (errSecNotAvailable)&lt;/code&gt;&lt;/a&gt; - que se você &lt;a href=&quot;https://developer.apple.com/documentation/security/errsecnotavailable&quot;&gt;ler a doc&lt;/a&gt; basicamente diz &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;No trust results are available.&lt;/code&gt;, no log de erro a seguinte mensagem aparece: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;No keychain is available.&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Bom, depois de muito investigar e achar diversos links de pessoas que passaram pelo mesmo problema e não acharam a causa raiz, ficou muito difícil para reproduzir o erro e corrigir o que causa ele de fato, mas para não sair de mãos vazias eu decidi seguir pela abordagem de assumir que ele vai ocorrer e tratar o erro de forma elegante.&lt;/p&gt;

&lt;p&gt;Dai veio um pensamento: Ok mas quando eu fizer essa possível tratativa do erro, como que vou comprovar que minha solução de fato trata o erro se eu nem consegui reproduzir ele? É basicamente uma solução às cegas, um tiro no escuro. Até podemos lançar um &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throw&lt;/code&gt; no meio do código pra fingir que o erro aconteceu, mas com certeza não é a mesma coisa que a API do módulo de Security te retornar esse erro de fato.&lt;/p&gt;

&lt;p&gt;Eu poderia usar o modo debug do xcode e tentar colocar um breakpoint e usar o &lt;a href=&quot;https://www.objc.io/issues/19-debugging/lldb-debugging/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;thread return&lt;/code&gt;&lt;/a&gt; para trocar o valor, mas iria gastar um bom tempo para entender quais comandos usar no lldb para modificar o retorno do método que eu quero… dai veio a ideia de usar o &lt;a href=&quot;https://frida.re/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Frida&lt;/code&gt;&lt;/a&gt; - lendo as docs eu vi que você pode usar &lt;a href=&quot;https://frida.re/docs/javascript-api/&quot;&gt;APIs em JS&lt;/a&gt; para poder modificar os retornos, o que pareceu bem promissor e relativamente simples de fazer, e como no passado eu já tinha configurado e instalado Frida no meu macbook, decidi tentar.&lt;/p&gt;

&lt;p&gt;No final eu cheguei nesse código para forçar esse erro a acontecer, escrevi esse script que basicamente faz o hook na função nativa que consulta a keychain e força o retorno do erro que quero.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// keychain_hook_specific_error.js&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;secItemCopyMatching&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;findExportByName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Security&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;SecItemCopyMatching&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;secItemCopyMatching&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;Interceptor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;attach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;secItemCopyMatching&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;onEnter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;SecItemCopyMatching called&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;onLeave&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;retval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;SecItemCopyMatching returning -25291&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;retval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;25291&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;SecItemCopyMatching not found&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;blockquote&gt;
  &lt;p&gt;Lembrando que para usar o frida no iOS você precisa ter o dispositivo jailbroken ou escolher &lt;a href=&quot;https://frida.re/docs/modes/&quot;&gt;outro método de operação&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Com esse script, toda vez que a função &lt;a href=&quot;https://developer.apple.com/documentation/security/secitemcopymatching(_:_:)&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SecItemCopyMatching&lt;/code&gt;&lt;/a&gt; for chamada, o retorno dela será alterado para o código de erro &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-25291&lt;/code&gt; para simular o erro que quero testar. Dai depois disso bastou executar o seguinte comando:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;ID_DO_SEU_DEVICE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# serve tanto para simulador quanto device fisico.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -F pra pegar o app que estiver rodando no momento, portanto abra o app antes de rodar esse comando&lt;/span&gt;
frida &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$ID_DO_SEU_DEVICE&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-F&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; ./keychain_hook_specific_error.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Agora que que esse script está rodando, toda vez que qualquer parte do meu app chamar essa função do módulo de Security, aquele erro vai ser retornado conforme eu configurei, dessa forma eu consigo comprovar que meu código está funcionando pois o módulo literalmente retornou esse erro, só precisei dar um empurrãozinho.&lt;/p&gt;

&lt;p&gt;Esse foi um exemplo simples, mas já da pra ter uma ideia do poder do frida para fazer debug em runtime, e o melhor de tudo é que você não precisa modificar o código fonte do app para isso, muito menos saber onde que esse código está, você pode fazer o hook em qualquer função nativa ou gerenciada que quiser.&lt;/p&gt;

&lt;p&gt;Além disso vale ressaltar que eu usei apenas 2 módulos do projeto (&lt;a href=&quot;https://frida.re/docs/javascript-api/#interceptor&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Interceptor&lt;/code&gt;&lt;/a&gt; e &lt;a href=&quot;https://frida.re/docs/javascript-api/#module&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Module&lt;/code&gt;&lt;/a&gt;) mas existem outras que podem ser usados.&lt;/p&gt;

&lt;p&gt;Tiveram pelo menos mais outras 2 vezes onde eu usei Frida e ferramentas que usam Frida por baixo dos panos (como o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;objection&lt;/code&gt;) para resolver problemas como esse, eu gostei que consegui chegar em uma solução bacana mais rápido do que eu esperava, e ainda por cima com evidências sólidas que minha solução funcionava - o que é muito bom, eu poderia citar elas aqui mas o post vai ficar longo demais, com o exemplo que eu dei já deu para entender por cima como uma ferramenta dessa pode ajudar no fluxo de debug.&lt;/p&gt;

&lt;h2 id=&quot;conclusão&quot;&gt;Conclusão&lt;/h2&gt;

&lt;p&gt;Nesse post passamos um pouco sobre ferramentas de que são usadas na área de segurança da informação, dei alguns exemplos e aprofundamos um pouco mais na ferramenta &lt;a href=&quot;https://frida.re/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Frida&lt;/code&gt;&lt;/a&gt; dando um exemplo bem simples.&lt;/p&gt;

&lt;p&gt;A principal mensagem que quero que leve desse post é não ficar preso as ferramentas tradicionais por estar acostumado a usá-la.&lt;/p&gt;

&lt;p&gt;Explore alternativas, até aquelas que são de outras áreas se realmente tiver interesse. Saber identificar as ““melhores”” ferramentas para cada caso pode te pagar dividendos, uma analogia interessante e meio exagerada para se pensar é: você consegue furar uma parede usando uma parafusadera? Não manjo muito de obras mas acredito que dependendo da potência dela e o material da parede até deve conseguir sim, mas sem dúvidas uma ferramenta própria para isso seria bem mais fácil.&lt;/p&gt;
</description>
        <pubDate>Thu, 20 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://blog.victorlpgazolli.dev/using-frida-when-developing-mobile-apps/</link>
        <guid isPermaLink="true">https://blog.victorlpgazolli.dev/using-frida-when-developing-mobile-apps/</guid>
        
        
        <category>mobile</category>
        
      </item>
    
      <item>
        <title>Renderização Declarativa - React Reconciler</title>
        <description>&lt;p&gt;&lt;img src=&quot;../_assets/here_to_help.png&quot; alt=&quot;xkcd 1831: Here to Help&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;introdução&quot;&gt;Introdução&lt;/h2&gt;

&lt;p&gt;Eu fiz esse post aqui como forma de eu aprofundar no tema de renderização declarativa, minha ideia é abordar alguams bibliotecas que funcionam dessa forma e entender com mais profundidade as diferenças de abordagens entre cada ferramenta.&lt;/p&gt;

&lt;p&gt;Eu quero cobrir tanto o React Reconciler quanto o Jetpack Compose Runtime, e talvez outras ferramentas que eu for encontrando no caminho. Por hora vamos começar com o React Reconciler.&lt;/p&gt;

&lt;p&gt;Disclaimer: Nesse artigo vou procurar colocar referencias das informações que eu estou compartilhando, mas é importante ressaltar que essas informações podem mudar com o tempo ou até mesmo eu posso cometer algum erro, portanto minha recomendação é ler este artigo com o ‘livro de regras embaixo do braço’ e sempre verificar a documentação oficial das ferramentas.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;react&quot;&gt;React&lt;/h2&gt;

&lt;p&gt;É uma biblioteca bem conhecida na web, e eu particularmente já usei bastante em projetos usando react-native. Poderíamos falar especificamente do react native, mas como a ideia é falar sobre a renderização declarativa, vou abordar apenas o react.&lt;/p&gt;

&lt;p&gt;Eu imagino que você já deve ter ouvido falar algo sobre ou talvez até desenvolvido alguma aplicação que utilize react, se não teve contato com a ferramenta não tem problema, vamos aprofundando aos poucos. Para iniciar um projeto react é bem simples, basta criar um elemento “root” e chamar uma função passando um componente para ser renderizado:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;createRoot&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;react-dom/client&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//react-dom@19&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;./App&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;domNode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createRoot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;domNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;App&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Vamos explorar um pouco como o react-dom funciona por baixo dos panos, e como que só esse trecho de código ja permite que voce renderize e atualize a interface do usuário de forma declarativa.&lt;/p&gt;

&lt;p&gt;Procurando no código fonte do react-dom, podemos &lt;a href=&quot;https://github.com/facebook/react/blob/v19.0.0/packages/react-dom/src/client/ReactDOMRoot.js#L161&quot;&gt;encontrar a função &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;createRoot&lt;/code&gt; aqui&lt;/a&gt;. esse é um código exemplo de como ele funciona:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;RootType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ReactElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createRoot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Element&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Document&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DocumentFragment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateRootOptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;RootType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/*
        usa-se o options para fazer uma serie de configurações que nesse momento não são importantes
    */&lt;/span&gt;
        
    &lt;span class=&quot;c1&quot;&gt;// react-reconciler/src/ReactFiberReconciler&lt;/span&gt;
     &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; 
        &lt;span class=&quot;nx&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/* ...demais configurações... */&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ReactDOMRoot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Perceba que o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;createRoot&lt;/code&gt; faz algumas configurações que no momento não são relevantes, importante é que ele chama a função &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;createContainer&lt;/code&gt;, que vem de uma biblioteca chamada &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;react-reconciler&lt;/code&gt;. Ou seja, a lib react-dom sozinha não cuida da renderização dos elementos, ela delega essa responsabilidade para a biblioteca &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;react-reconciler&lt;/code&gt;, o que faz sentido pois ter essa logica abstraida em uma lib separada de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;react-dom&lt;/code&gt; permite que o reconciliador possa ser importado e utilizado de forma independente.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/meme-reconciliation-01.png&quot; alt=&quot;reconciler &amp;amp; renderer&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;reconciler--renderer&quot;&gt;Reconciler &amp;amp; Renderer&lt;/h3&gt;

&lt;p&gt;O react reconciler é responsavel em fazer a gestão das mudanças de estado e props dos componentes, basicamente ele é o motor que faz toda a lógica de comparação entre uma versão D e D+1 da árvore de componentes, e decide quais componentes precisam ser atualizados, removidos ou adicionados.&lt;/p&gt;

&lt;p&gt;Além dessa gestão de mudanças sendo feita, existe outro componente que cuida de como essas mudanças são aplicadas na interface do usuário, e é ai que entra o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;renderer&lt;/code&gt;, ele é a camada que faz a ponte entre o reconciler e a plataforma onde a aplicação está rodando, seja ela web, mobile ou desktop.&lt;/p&gt;

&lt;p&gt;Por conta dessa arquitetura desacoplada, que permite que sejam criados vários renderers, APIs que se conectam com o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;react-reconciler&lt;/code&gt; e fazem a implementação na sua plataforma especifica, uma imagem bacana sobre isso:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/reconciler_renderer.png&quot; alt=&quot;reconciler &amp;amp; renderer&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;algoritmo&quot;&gt;Algoritmo&lt;/h3&gt;

&lt;p&gt;Agora sabemos que ele é quem faz todo o trabalho pesado de comparar e decidir o que precisa ser atualizado, varrendo toda a arvore de componentes e fazendo essas comparações.&lt;/p&gt;

&lt;p&gt;Em uma perpectiva de performance, quanto menos nós sendo atualizados desnecessáriamente, melhor. Essa comparação e identificação é a chave para uma renderização eficiente.&lt;/p&gt;

&lt;p&gt;Links para entender mais sobre o algoritmo de reconciliação:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://angular.love/inside-fiber-in-depth-overview-of-the-new-reconciliation-algorithm-in-react&quot;&gt;Inside Fiber: in-depth overview of the new reconciliation algorithm in React&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://medium.com/react-in-depth/the-how-and-why-on-reacts-usage-of-linked-list-in-fiber-67f1014d0eb7&quot;&gt;The how and why on React’s usage of linked list in Fiber to walk the component’s tree&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/facebook/react/tree/v19.0.0/packages/react-reconciler&quot;&gt;source code: react-reconciler&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/fiber.png&quot; alt=&quot;reconciler &amp;amp; renderer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Essas informações salvas dentro desse nó são importantes para que o Reconciler saiba qual nó ele precisa atualizar, e qual ele pode simplesmente ignorar pois não houve mudanças.&lt;/p&gt;

&lt;h4 id=&quot;stack-reconciler-e-fiber-reconciler&quot;&gt;Stack Reconciler e Fiber Reconciler&lt;/h4&gt;

&lt;p&gt;Na versão 15 e anteriores, o react utilizava um algoritmo de reconciliação chamado de “Stack Reconciler”, a desvantagem dele era a performance: ele percorria toda a arvore de componentes de forma sincrona, componente a componente fazendo aplicando as mudanças, isso é passivo a problemas de performance como drop de frames em animações.&lt;/p&gt;

&lt;p&gt;Por mais que isso fosse prejudicial, era possivel contornar esse problema de performance fazendo esse trabalho no tempo livre no final dos frames, fazendo uso do &lt;a href=&quot;https://developer.chrome.com/blog/using-requestidlecallback&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requestIdleCallback&lt;/code&gt;&lt;/a&gt;. Essa saída ajuda mas não é bala de prata porque nós ainda teriamos que percorrer a arvore toda de qualquer forma.&lt;/p&gt;

&lt;p&gt;Para resolver de forma definitiva esse problema de performance, foi necessário permitir que o algoritmo pudesse pausar e continuar a execução de um update, além disso esse novo algoritmo introduziu formas de aplicar atualizações com base na prioridade (&lt;a href=&quot;https://www.geeksforgeeks.org/reactjs/how-does-concurrent-mode-help-in-improving-the-user-experience/&quot;&gt;link para ler mais sobre&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../_assets/meme-fiber-reconciliation.gif&quot; alt=&quot;meme the future is now old man&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Esse esquema de pausar e continuar os trabalhos, permite que o react quebre todo o trabalho de atualização em pequenos pacotes, essa técnica é chamada de “time-slicing”:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/reactjs/explain-the-concept-of-time-slicing-in-concurrent-mode/&quot;&gt;Explain the concept of time-slicing in Concurrent Mode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A versão 16 do react foi lançada em 2017, então ja faz um tempinho que teve essa mudança para o novo algoritmo, portanto talvez você ja deve ter percebido ou ouvido falar que alguns dos updates de estados no react não ocorrem de forma sincrona, em resumo é justamente isso que o novo algoritmo permite.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://legacy.reactjs.org/blog/2017/09/26/react-v16.0.html&quot;&gt;Lançamento do React v16.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;árvore-de-componentes-react&quot;&gt;Árvore de Componentes React&lt;/h4&gt;

&lt;p&gt;O ‘Fiber Reconciler’ deu nome de cada ‘trabalho’ a ser feito nos componentes como um nodo &lt;a href=&quot;https://github.com/facebook/react/blob/6e4f7c788603dac7fccd227a4852c110b072fe16/packages/react-reconciler/src/ReactFiber.js#L78&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fiber&lt;/code&gt;&lt;/a&gt;, ele é a representação de um trabalho pendente ou um trabalho ja feito.&lt;/p&gt;

&lt;p&gt;Esse trabalho a ser feito podem set vários tipos de tarefas, como por exemplo: Executar um ‘Efeito’ como useEffect (&lt;a href=&quot;https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberHooks.js#L2616&quot;&gt;link&lt;/a&gt;), ou atualizar o estado de um componente (&lt;a href=&quot;https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberHooks.js#L3708&quot;&gt;link&lt;/a&gt;) e assim por diante.&lt;/p&gt;

&lt;p&gt;Mas somente saber o que precisa ser feito não da para construir uma arvore de componentes, precisamos de relações entre cada nodo, portanto dentro de um Fiber temos informações extras que nos ajudam a montar uma arvore, como por exemplo o estado atual do componente, as props, e referencias para os filhos, irmãos e pai, e lista de atualizações pendentes.&lt;/p&gt;

&lt;p&gt;Tendo uma estrutura de árvore fica bem mais fácil navegar entre os nodos, saber qual deles tem alguma pendência, as dependencias dos nodos entre si, etc. E para poder fazer tudo isso acontecer foi quebrado em fases.&lt;/p&gt;

&lt;p&gt;Na primeira fase do algoritmo (normalmente chamada de “Render phase”), o reconciler precisa entender primeiro qual nó precisa ser adicionado, atualizado, deletado, e também se teve algum efeito colateral a ser computado.&lt;/p&gt;

&lt;p&gt;Esses componentes “alterados” são justamente o que vão ser usados na segunda fase!&lt;/p&gt;

&lt;p&gt;Para ficar tangível esse comportamento, &lt;a href=&quot;https://vimeo.com/302222454&quot;&gt;sugiro ver esse vídeo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Na segunda fase (normalmente chamada de “Commit phase”), o reconciler teve tempo de calcular todas as mudanças necessárias, portanto agora ele precisa fazer (nessa ordem):&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/facebook/react/blob/95a313ec0b957f71798a69d8e83408f40e76765b/packages/react-reconciler/src/ReactFiberScheduler.js#L376&quot;&gt;executar alterações na interface do usuário&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/facebook/react/blob/95a313ec0b957f71798a69d8e83408f40e76765b/packages/react-reconciler/src/ReactFiberScheduler.js#L465&quot;&gt;executar os efeitos colaterais&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Depois que todas as mudanças foram aplicadas, o reconciler limpa a fila de tarefas e espera o próximo update :)
E assim finalizamos o ciclo de vida de um update no react.&lt;/p&gt;

&lt;h3 id=&quot;referências&quot;&gt;Referências&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://legacy.reactjs.org/docs/reconciliation.html&quot;&gt;React Docs - Reconciliation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://legacy.reactjs.org/docs/faq-internals.html&quot;&gt;React Docs - React Fiber Architecture&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Thu, 16 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://blog.victorlpgazolli.dev/react-reconciler-vs-compose-runtime/</link>
        <guid isPermaLink="true">https://blog.victorlpgazolli.dev/react-reconciler-vs-compose-runtime/</guid>
        
        
        <category>mobile,</category>
        
        <category>javascript</category>
        
      </item>
    
  </channel>
</rss>
