Servizio SystemSospendi

In Android 9 e versioni precedenti è presente un thread in libsuspend responsabile di avviare la sospensione del sistema. Android 10 introduce una funzionalità equivalente in un servizio HIDL SystemSospendi. Questo servizio si trova nell'immagine di sistema ed è gestito dalla piattaforma Android. La logica di libsuspend rimane in gran parte la stessa, ad eccezione di ogni spazio utente il processo che blocca la sospensione del sistema deve comunicare con SystemPause.

libsuspend e libpower

In Android 10, il servizio SystemSospendi sostituisce libsuspend. libpower è stato reimplementato in modo che si basi su al servizio SystemSospendi invece che /sys/power/wake[un]lock senza modificare l'API C.

Questo pseudocodice mostra come implementare acquire_wake_lock e release_wake_lock.


static std::unordered_map<std::string, sp<IWakeLock>> gWakeLockMap;

int acquire_wake_lock(int, const char* id) {
    ...
    if (!gWakeLockMap[id]) {
        gWakeLockMap[id] = suspendService->acquireWakeLock(WakeLockType::PARTIAL, id);
    }
    ...
    return 0;
}

int release_wake_lock(const char* id) {
    ...
    if (gWakeLockMap[id]) {
        auto ret = gWakeLockMap[id]->release();
        gWakeLockMap[id].clear();
        return 0;
    }
    ...
    return -1;
}

Thread di esecuzione

Il servizio SystemSospendi tiene traccia del numero di wakelock emessi con un contatore di sospensione. Ha due thread di esecuzione:

  • Il thread principale risponde alle chiamate a binder.
  • Il sistema di controllo dei thread sospendi viene sospeso.

Thread principale

Il thread principale risponde alle richieste dei client per l'allocazione di nuovi wakelock, Aumenta/diminuisce il contatore di sospensione.

Sospendi thread

Il thread di sospensione esegue la seguente sequenza in un loop:

  1. Leggi da /sys/power/wakeup_count.
  2. Acquisisci il mutex. Questo assicura che il thread di sospensione non tocchi il contatore di sospensione mentre il thread main tenta di di aumentarla o diminuirla. Il thread principale è bloccato sull'emissione o la rimozione dei wakelock quando il contatore di sospensione ha raggiunto lo zero e il thread sospendi sta tentando di eseguire.
  3. Attendi che il contatore sia uguale a zero.
  4. Scrivi il valore letto da /sys/power /wakeup_count (dal passaggio 1) in questo file. Se la scrittura non riesce, torna all'inizio del loop
  5. Avvia la sospensione del sistema scrivendo mem in /sys/power/state.
  6. Rilascia il silenziatore.

Quando viene restituita una richiesta di wakelock, il thread di sospensione viene bloccato.

Figura 1. Sospendi loop di thread
.

API SystemPause

L'API SystemSospendi è composta da due interfacce. L'interfaccia HIDL viene utilizzata dai processi nativi per acquisire i wakelock e l'interfaccia AIDL viene utilizzata la comunicazione tra SystemServer e SystemPause.

Interfaccia ISystemSospendi HIDL


enum WakeLockType : uint32_t {
    PARTIAL,
    FULL
};

interface IWakeLock {
    oneway release();
};

interface ISystemSuspend {
    acquireWakeLock(WakeLockType type, string debugName)
        generates (IWakeLock lock);
};

Ogni client che richiede un wakelock riceve un ID univoco IWakeLock istanza. Questo è diverso da /sys/power/wake_lock, che consente di usare il wakelock con lo stesso nome. Se un cliente che detiene una L'istanza IWakeLock viene terminata, il driver binder e Il servizio SystemSospendi esegue la pulizia.

Interfaccia AIDL ISospendiControlService

ISospendiControlService è destinato a essere utilizzato solo da SystemServer.


interface ISuspendCallback {
     void notifyWakeup(boolean success);
}

interface ISuspendControlService {
    boolean enableAutosuspend();
    boolean registerCallback(ISuspendCallback callback);
    boolean forceSuspend();
}

L'uso di Android HIDL offre i seguenti vantaggi:

  • Se il processo di blocco della sospensione si interrompe, può essere inviata una notifica a SystemSospendi.
  • È possibile assegnare un callback al thread responsabile della sospensione del sistema.