APEX in Android D: La cosa più importante dai tempi di Project Treble?

Google sta lavorando su APEX: aggiornamento delle librerie di sistema come una distribuzione Linux standard. Previsto in Android Q, APEX potrebbe essere la cosa più importante dai tempi di Project Treble.

L'implementazione di APEX è probabilmente il problema più grande che Google ha dovuto affrontare dall'introduzione di Project Treble. Cos'è APEX e come cambierà Android la sua introduzione?

L'idea alla base di APEX di per sé è piuttosto comune nelle distribuzioni GNU/Linux di tutti i giorni: aggiornamenti dei pacchetti destinati a sezioni specifiche del set di librerie Linux. Ma è qualcosa che Google non ha mai provato a fare dato che Android ha utilizzato una partizione RO (sola lettura) in cui tutte le librerie di sistema e i framework vengono archiviati rispetto alle solite partizioni RW (lettura-scrittura) utilizzate nella maggior parte delle distribuzioni Linux, rendendo il processo di aggiornamento standard inadatto.

Le librerie sono codice precompilato che può essere utilizzato in altri programmi. I metodi comunemente utilizzati possono essere inseriti in librerie da richiamare per le app Android, riducendo la dimensione degli APK poiché non sarà necessario reimplementare lo stesso codice su più app. Puoi trovare molte librerie di sistema preinstallate nelle directory /system/lib e /system/lib64. Le librerie di sistema Android in genere non vengono aggiornate individualmente, ma vengono aggiornate come parte degli aggiornamenti delle piattaforme Android tramite un aggiornamento OTA. D'altra parte, le librerie nelle distribuzioni Linux possono essere aggiornate individualmente. Con l'introduzione di APEX, le librerie di sistema in Android possono essere aggiornate individualmente come le app Android. Il vantaggio principale di ciò è che gli sviluppatori di app saranno in grado di sfruttare le librerie aggiornate senza attendere che un OEM implementi un aggiornamento completo del sistema. Entriamo nei dettagli più tecnici su come funziona APEX.

In che modo APEX cambierà il modo in cui vengono aggiornate le librerie?

APEX è un ecosistema che ha costretto (o meglio, sta costringendo) Google a riconsiderare il modo in cui Android carica tutte le librerie e i file da una partizione non standard diversa da /system.

Innanzitutto dobbiamo specificare la differenza tra una libreria condivisa e una libreria statica. Una libreria condivisa è una libreria (di solito un file chiamato libkind.so) che non include tutto il codice necessario per essere eseguita al suo interno ma è effettivamente "collegata" ad altre librerie fornendo il codice, mentre una libreria statica è, come puoi immaginare, una libreria che non dipende da altre librerie e ha tutto incluso staticamente all'interno del file.

Android storicamente configura il percorso della libreria (conosciuto come LD_LIBRARY_PATH nel mondo Linux) con un unico file chiamato ld.config.txt [0] per configurare i percorsi di ricerca consentiti per le librerie condivise necessarie sia per il binario che per un altro biblioteca. Questi percorsi sono codificati nella configurazione e non sono espandibili. Questo layout, inclusa la partizione di sistema di sola lettura, porta a librerie non aggiornabili a meno che l'utente non installi un aggiornamento Android OTA. Google ha risolto questo problema consentendo di estendere il percorso di ricerca consentendo ai singoli pacchetti APEX di fornire il proprio ld.config.txt che includeva i percorsi delle librerie extra (e aggiornati) in essi contenuti.

Sebbene questa mossa abbia risolto uno dei problemi principali, c’erano ancora alcuni problemi seri da superare. Prima di tutto: stabilità ABI (Application Binary Interface). Le librerie dovrebbero sempre esportare un set stabile di interfacce per consentire ad altre app e librerie di continuare a funzionare con lo stesso protocollo anche con la libreria aggiornata. Google sta lavorando attivamente su questo cercando di creare un'interfaccia C stabile tra le librerie APEX.

Ma un APEX non è limitato solo alle librerie e ai file binari. In effetti, può contenere file di configurazione, aggiornamenti del fuso orario e alcuni framework Java (conscrypt al momento della scrittura).

Ecco alcuni esempi degli attuali pacchetti APEX forniti da AOSP:

  • com.android.runtime: ART e runtime bionico (binari e librerie)
  • com.android.tzdata: dati TimeZone e ICU (librerie e dati di configurazione)
  • com.android.resolv: libreria utilizzata da Android per risolvere richieste relative alla rete (librerie)
  • com.android.conscrypt: un fornitore di sicurezza Java (framework Java)

Come viene installato e strutturato un pacchetto APEX?

Un pacchetto APEX è un semplice archivio zip (come un APK) che può essere installato dal nostro pratico ADB (a questo punto in fase di sviluppo) e, successivamente, dall'utente stesso tramite un gestore di pacchetti (come Google Play o manualmente tramite il pacchetto Android installatore).

Il layout del ZIP è il seguente:

Immergiamoci in questo.

apex_manifest.json specifica il nome e la versione del pacchetto.

apex_payload.img è un'immagine micro-filesystem (formattata come EXT4).

Gli altri file fanno parte del processo di verifica utilizzato per installare il pacchetto. Diamo un'occhiata.

La presenza di AndroidManifest.xml, anche se utilizzato principalmente nelle applicazioni, ci aiuta a capire che la maggior parte dell'implementazione utilizzata per un'installazione APK standard viene riutilizzata anche per questi pacchetti. In effetti, viene controllata solo l'estensione per differenziarli.

IL META-INF/ directory ha il certificato del pacchetto e utilizza lo stesso meccanismo dei normali APK. Quindi questi pacchetti vengono verificati da una coppia di chiavi privata/pubblica in fase di esecuzione prima che all'utente sia consentito installare un aggiornamento. Ma per Google questo non è bastato, quindi hanno aggiunto altri due livelli di sicurezza. Stanno utilizzando dm-verity per verificare l'integrità dell'immagine e le verifiche AVB (Android Verified Boot) per assicurarsi che l'immagine provenga da una fonte attendibile. Nel peggiore dei casi, il pacchetto APEX verrà rifiutato.

Se tutti i passaggi di verifica hanno esito positivo, l'immagine verrà contrassegnata come valida e sostituirà la variante del sistema al successivo riavvio.

Come viene installata un'immagine all'avvio?

Iniziamo dando un'occhiata agli APEX attualmente installati sul mio dispositivo (un emulatore)

Come puoi vedere, i pacchetti preinstallati sono archiviati in /system/apex/ e tutti sono attualmente alla versione numero 1. Ma cosa succede quando viene attivato un APEX? Utilizzeremo nuovamente com.android.tzdata come esempio.

Riavviamo il dispositivo e analizziamo il logcat.

Le prime 2 righe forniscono informazioni sufficienti per comprendere l'origine del pacco e dove sarà installato: /apex/, una nuova directory introdotta in Android Q che verrà utilizzata per archiviare i file attivati Pacchetti.

Dopo che il pacchetto è stato verificato con successo con AVB e la chiave pubblica corrisponde, APEX viene montato utilizzando un dispositivo loop su /dev/block/loop0, rendendo il file system EXT4 accessibile al sistema. Un dispositivo loop è uno pseudo-dispositivo che rende un file accessibile come dispositivo a blocchi, rendendo accessibile il contenuto di quel file come punto di montaggio.

A questo punto APEX non è ancora utilizzato a causa del suffisso @1 (che indica la versione del pacchetto). Per far sapere finalmente al sistema che il nostro pacchetto è stato attivato con successo, verrà montato su /apex/com.android.tzdata dove Android si aspetta attivamente che tzdata risieda. Un montaggio di associazione si sovrappone a una directory o un file esistente in un punto diverso. [1]

L'implementazione APEX è interamente contenuta in un unico repository sotto AOSP. [2] La directory apexd (daemon APEX) ha il codice in esecuzione su Android. La directory apexer contiene il codice utilizzato dal sistema di compilazione per creare i pacchetti APEX.

Qual è lo scopo?

A questo punto non posso fare altro che speculare. La mia ipotesi migliore è che Google stia cercando di creare un set principale di pacchetti APEX che possano essere aggiornati da Google per eventualmente creare un nucleo base unificato di Android condiviso tra i fornitori, rendendo possibili solo aggiornamenti di "sistema", ma utilizzando un unico pacchetto aggiornamenti.

Tutti i dispositivi supporteranno APEX?

No. Ad esempio, apexd richiede che /data/apex sia disponibile subito dopo l'avvio per aggiornare tutti i moduli Android. Con FDE (Full-disk Encryption), /data/apex viene crittografato finché il dispositivo non viene sbloccato dall'utente, rendendo APEX sostanzialmente inutile poiché all'avvio verranno caricate solo le varianti APEX del sistema. Oltre a ciò, tutti i dispositivi dovrebbero supportare APEX, ma necessitano di alcune patch del kernel (molte delle quali sono correzioni trovate da Google durante il gioco con i dispositivi loop). [3] [4]


Fonti [0], [1], [2], [3], [4]