Cache dell'APK

Questo documento descrive la progettazione di una soluzione di memorizzazione nella cache APK per l'installazione rapida di app precaricate su un dispositivo che supporta partizioni A/B.

Gli OEM possono posizionare precaricati e app popolari nella cache APK archiviata nella partizione B, per lo più vuota, sui nuovi dispositivi con partizionamento A/B senza influire sullo spazio dati rivolto all'utente. Avendo una cache APK disponibile sul dispositivo, i dispositivi nuovi o recentemente ripristinati alle impostazioni di fabbrica sono pronti per l'uso quasi immediatamente, senza bisogno di scaricare file APK da Google Play.

Casi d'uso

  • Memorizza le app precaricate nella partizione B per una configurazione più rapida
  • Memorizza le app più popolari nella partizione B per un ripristino più rapido

Prerequisiti

Per utilizzare questa funzionalità, il dispositivo necessita di:

  • Versione Android 8.1 (O MR1) installata
  • Partizione A/B implementata

Il contenuto precaricato può essere copiato solo durante il primo avvio. Questo perché sui dispositivi che supportano gli aggiornamenti di sistema A/B, la partizione B in realtà non memorizza i file di immagine del sistema, ma invece precarica contenuti come risorse demo al dettaglio, file OAT e cache APK. Dopo che le risorse sono state copiate nella partizione /data (questo avviene al primo avvio), la partizione B verrà utilizzata dagli aggiornamenti over-the-air (OTA) per scaricare le versioni aggiornate dell'immagine di sistema.

Pertanto la cache APK non può essere aggiornata tramite OTA; può essere precaricato solo in fabbrica. Il ripristino delle impostazioni di fabbrica influisce solo sulla partizione /data. La partizione del sistema B ha ancora il contenuto precaricato finché non viene scaricata l'immagine OTA. Dopo il ripristino delle impostazioni di fabbrica, il sistema eseguirà nuovamente il primo avvio. Ciò significa che la memorizzazione nella cache dell'APK non è disponibile se l'immagine OTA viene scaricata nella partizione B e quindi il dispositivo viene ripristinato alle impostazioni di fabbrica.

Implementazione

Approccio 1. Contenuto sulla partizione system_other

Pro : il contenuto precaricato non viene perso dopo il ripristino delle impostazioni di fabbrica: verrà copiato dalla partizione B dopo il riavvio.

Contro : richiede spazio sulla partizione B. L'avvio dopo il ripristino delle impostazioni di fabbrica richiede tempo aggiuntivo per copiare il contenuto precaricato.

Affinché i precaricamenti vengano copiati durante il primo avvio, il sistema richiama uno script in /system/bin/preloads_copy.sh . Lo script viene chiamato con un singolo argomento (percorso del punto di montaggio di sola lettura per la partizione system_b ):

Per implementare questa funzionalità, apportare queste modifiche specifiche del dispositivo. Ecco un esempio tratto da Marlin:

  1. Aggiungi lo script che esegue la copia nel file device-common.mk (in questo caso, device/google/marlin/device-common.mk ), in questo modo:
    # Script that copies preloads directory from system_other to data partition
    PRODUCT_COPY_FILES += \
        device/google/marlin/preloads_copy.sh:system/bin/preloads_copy.sh
    
    Trova l'origine dello script di esempio in: device/google/marlin /preloads_copy.sh
  2. Modifica il file init.common.rc per creare la directory /data/preloads e le sottodirectory necessarie:
    mkdir /data/preloads 0775 system system
    mkdir /data/preloads/media 0775 system system
    mkdir /data/preloads/demo 0775 system system
    
    Trova l'origine del file init di esempio su: device/google/marlin/init.common.rc
  3. Definisci un nuovo dominio SELinux nel file preloads_copy.te :
    type preloads_copy, domain, coredomain;
    type preloads_copy_exec, exec_type, vendor_file_type, file_type;
    
    init_daemon_domain(preloads_copy)
    
    allow preloads_copy shell_exec:file rx_file_perms;
    allow preloads_copy toolbox_exec:file rx_file_perms;
    allow preloads_copy preloads_data_file:dir create_dir_perms;
    allow preloads_copy preloads_data_file:file create_file_perms;
    allow preloads_copy preloads_media_file:dir create_dir_perms;
    allow preloads_copy preloads_media_file:file create_file_perms;
    
    # Allow to copy from /postinstall
    allow preloads_copy system_file:dir r_dir_perms;
    
    Trova un file di dominio SELinux di esempio su: /device/google/marlin/+/main/sepolicy/preloads_copy.te
  4. Registra il dominio in un nuovo /sepolicy/file_contexts file:
    /system/bin/preloads_copy\.sh     u:object_r:preloads_copy_exec:s0
    
    Trova un esempio di file di contesto SELinux su: device/google/marlin/sepolicy/preloads_copy.te
  5. In fase di compilazione, la directory con il contenuto precaricato deve essere copiata nella partizione system_other :
    # Copy contents of preloads directory to system_other partition
    PRODUCT_COPY_FILES += \
        $(call find-copy-subdir-files,*,vendor/google_devices/marlin/preloads,system_other/preloads)
    
    Questo è un esempio di modifica in un Makefile che consente di copiare le risorse della cache APK dal repository Git del fornitore (nel nostro caso era vendor/google_devices/ marlin/preloads) nella posizione sulla partizione system_other che verrà successivamente copiata in /data/preloads quando il dispositivo si avvia per la prima volta. Questo script viene eseguito in fase di compilazione per preparare l'immagine system_other. Si prevede che i contenuti precaricati siano disponibili in vendor/google_devices/marlin/preloads. L'OEM è libero di scegliere il nome/percorso effettivo del repository.
  6. La cache APK si trova in /data/preloads/file_cache e ha il seguente layout:
    /data/preloads/file_cache/
        app.package.name.1/
              file1
              fileN
        app.package.name.N/
    
    Questa è la struttura di directory finale sui dispositivi. Gli OEM sono liberi di scegliere qualsiasi approccio di implementazione purché la struttura del file finale replichi quella sopra descritta.

Approccio 2. Il contenuto dell'immagine dei dati utente è stato flashato in fabbrica

Questo approccio alternativo presuppone che il contenuto precaricato sia già incluso nella directory /data/preloads sulla partizione /data .

Pro : funziona immediatamente: non è necessario personalizzare il dispositivo per copiare i file al primo avvio. Il contenuto è già nella partizione /data .

Contro : il contenuto precaricato viene perso dopo il ripristino delle impostazioni di fabbrica. Sebbene ciò possa essere accettabile per alcuni, potrebbe non funzionare sempre per gli OEM che ripristinano i dispositivi in ​​fabbrica dopo aver eseguito ispezioni di controllo qualità.

Un nuovo metodo @SystemApi, getPreloadsFileCache() , è stato aggiunto ad android.content.Context . Restituisce un percorso assoluto a una directory specifica dell'applicazione nella cache precaricata.

È stato aggiunto un nuovo metodo, IPackageManager.deletePreloadsFileCache , che consente di eliminare la directory preloads per recuperare tutto lo spazio. Il metodo può essere richiamato solo dalle app con SYSTEM_UID, ovvero server di sistema o Impostazioni.

Preparazione dell'app

Solo le applicazioni privilegiate possono accedere alla directory della cache di precaricamento. Per tale accesso, le app devono essere installate nella directory /system/priv-app .

Validazione

  • Dopo il primo avvio, il dispositivo dovrebbe avere contenuti nella directory /data/preloads/file_cache .
  • Il contenuto nella directory file_cache/ deve essere eliminato se lo spazio di archiviazione del dispositivo è basso.

Utilizza l'app ApkCacheTest di esempio per testare la cache dell'APK.

  1. Crea l'app eseguendo questo comando dalla directory root:
    make ApkCacheTest
    
  2. Installa l'app come applicazione privilegiata. (Ricorda, solo le app privilegiate possono accedere alla cache APK.) Ciò richiede un dispositivo rooted:
    adb root && adb remount
    adb shell mkdir /system/priv-app/ApkCacheTest
    adb push $ANDROID_PRODUCT_OUT/data/app/ApkCacheTest/ApkCacheTest.apk /system/priv-app/ApkCacheTest/
    adb shell stop && adb shell start
    
  3. Simula la directory della cache dei file e il suo contenuto, se necessario (richiedendo anche i privilegi di root):
    adb shell mkdir -p /data/preloads/file_cache/com.android.apkcachetest
    adb shell restorecon -r /data/preloads
    adb shell "echo "Test File" > /data/preloads/file_cache/com.android.apkcachetest/test.txt"
    
  4. Prova l'app. Dopo aver installato l'app e creato la directory test file_cache , apri l'app ApkCacheTest. Dovrebbe mostrare un file test.txt e il suo contenuto. Guarda questo screenshot per vedere come appaiono questi risultati nell'interfaccia utente.

    Figura 1. Risultati di ApkCacheTest