Analyse du cycle de vie des processus : Mécanismes de destruction et redémarrage du Launcher dans Android

Dans l'écosystème Android, la gestion de la mémoire et la survie des processus critiques, comme le Launcher, reposent sur l'ActivityManagerService (AMS). Le système dispose principalement de deux approches pour mettre fin à un processus via l'AMS :

  • killBackgroundProcesses : Cette méthode cible les processus en arrière-plan. Le flux remonte généralement jusqu'à killPackageProcessesLocked, puis invoque removeProcessLocked dans la ProcessList, aboutissant à l'appel de la méthode kill de l'objet ProcessRecord.
  • forceStopPackage : Une méthode plus radicale qui élimine tous les processus liés à une application et nettoie l'intégralité des composants (Activities, Services, etc.) enregistrés dans le system_server.

Analyse de la mort d'un processus : handleAppDiedLocked

Lorsqu'un processus meurt de manière inattendue (par exemple via un signal kill envoyé par ADB), l'AMS déclenche une procédure de nettoyage via handleAppDiedLocked. Voici une représnetation simplifiée de la logique interne : ```

@GuardedBy("this") private void effectuerNettoyageProcessusMort(ProcessRecord registreApp, boolean enCoursDeRedemarrage, boolean autoriserRelance) { int identifiantPid = registreApp.pid;

// Nettoyage des références internes à l'application
boolean estMaintenu = cleanUpApplicationRecordLocked(registreApp, enCoursDeRedemarrage, autoriserRelance, -1, false);

if (!estMaintenu && !enCoursDeRedemarrage) {
    // Journalisation de la trace d'appel pour débogage
    Log.i("AMS_DEBUG", "Suppression du processus : " + registreApp.processName);
    supprimerProcessusLru(registreApp);
    
    if (identifiantPid > 0) {
        ProcessList.remove(identifiantPid);
    }
}

if (mProfileData.getProfileProc() == registreApp) {
    reinitialiserProfiler();
}

}


### Le cycle de redémarrage du Launcher

Lorsqu'un processus comme `com.android.launcher3` est tué alors qu'il est au sommet de la pile (stack), le système réagit immédiatement via le `DeathRecipient` binder. La séquence de redémarrage suit généralement ce chemin : 1. `ActivityManagerService$AppDeathRecipient.binderDied()` : Réception du signal de mort.
2. `ActivityStackSupervisor.startSpecificActivity()` : Constatant que l'activité principale est absente, le système tente de relancer le processus.
3. `RootWindowContainer.resumeHomeActivity()` : Le système identifie que l'activité à relancer est l'écran d'accueil.
4. `ActivityStartController.startHomeActivity()` : Déclenchement effectif du lancement du Launcher.

### Hiérarchie des priorités : oom\_adj

Le système Android utilise une valeur appelée `oom_adj` (Out Of Memory Adjuster) pour déterminer quels processus doivent être sacrifiés en priorité en cas de pression mémoire. Plus la valeur est basse, plus le processus est prioritaire. | Constante ADJ | Valeur cible | Description |
|---|---|---|
| NATIVE\_ADJ | -1000 | Processus natifs gérés par init, hors contrôle AMS. |
| SYSTEM\_ADJ | -900 | Processus critique du system\_server. |
| PERSISTENT\_PROC\_ADJ | -800 | Applications système marquées comme `android:persistent="true"`. |

### Ajustement manuel de la priorité (Persistence)

Pour empêcher une application spécifique d'être recyclée par le Low Memory Killer (LMK), il est possible de modifier la logique d'attribution des scores ADJ dans le framework (`OomAdjuster.java`). Voici un exemple de modification permettant de verrouiller la priorité d'un processus spécifique : ```

private final boolean appliquerPrioriteOom(ProcessRecord appRecord, boolean global, long tempsActuel) {
    // ... logique existante de calcul de appRecord.curAdj ...

    // Injection d'une règle spécifique pour maintenir l'application active
    if ("com.mon.application.critique".equals(appRecord.processName)) {
        // On force un score proche des services persistants
        appRecord.curAdj = -700; 
    }

    if (appRecord.curAdj != appRecord.setAdj) {
        // Application effective du score via le driver du noyau
        ProcessList.setOomAdj(appRecord.pid, appRecord.uid, appRecord.curAdj);
        appRecord.setAdj = appRecord.curAdj;
    }
    
    // ... suite du flux ...
    return true;
}

Surveillance de la mémoire et LMKD

Le LMKD (Low Memory Killer Daemon) surveille en permanence l'état de la RAM. Lorsque la mémoire libre tombe sous certains seuils définis par minfree, le noyau comence à tuer les processus ayant le score oom_score_adj le plus élevé. Pour diagnostiquer l'état d'un processus en production, les commandes suivantes sont essentielles : - dumpsys meminfo : Vue globale de la consommation RAM.

  • cat /proc/<PID>/oom_score_adj : Vérification du score d'ajustement actuel d'un processus.

Ce mécanisme garantit que même si le Launcher3 rencontre une erreur fatale ou est tué manuellement, l'ActivityTaskManagerService détectera l'absence de l'activité "Home" et forcera la recréation du processus pour maintenir l'utilisabilité de l'interface utilisateur.

Étiquettes: Android AMS framework Launcher3 OomAdjuster

Publié le 2 août à 18h31