In Android 9 e versioni precedenti è presente un thread in libsuspend
responsabile dell'avvio della sospensione del sistema. Android 10
introduce una funzionalità equivalente in un servizio HIDL SystemSuspend.
Questo servizio si trova nell'immagine di sistema ed è fornito dalla piattaforma Android.
La logica di libsuspend
rimane in gran parte invariata, tranne per il fatto che ogni processo
userspace che blocca la sospensione del sistema deve comunicare con SystemSuspend.
libsuspend e libpower
In Android 10, il servizio SystemSuspend sostituisce
libsuspend
. libpower
è stato implementato nuovamente per fare affidamento sul servizio SystemSuspend anziché su /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 SystemSuspend tiene traccia del numero di wake lock emessi con un contatore di sospensione. Ha due thread di esecuzione:
- Il thread principale risponde alle chiamate di Binder.
- Il thread suspend controlla la sospensione del sistema.
Thread principale
Il thread principale risponde alle richieste dei client di allocare nuovi wake lock, incrementando/decrementando il contatore di sospensione.
Sospendi thread
Il thread di sospensione esegue le seguenti operazioni in un ciclo:
- Leggi da
/sys/power/wakeup_count
. - Acquisisci il mutex. In questo modo, il thread di sospensione non tocca il contatore di sospensione mentre il thread principale tenta di incrementarlo o decrementarlo. Il thread principale è bloccato durante l'emissione o la rimozione di wake lock quando il contatore di sospensione ha raggiunto lo zero e il thread sospensione sta tentando di essere eseguito.
- Attendi che il contatore sia uguale a zero.
- Scrivi in questo file il valore letto da
/sys/power /wakeup_count
(dal passaggio 1). Se la scrittura non va a buon fine, torna all'inizio del ciclo - Avvia la sospensione del sistema scrivendo
mem
in/sys/power/state
. - Rilascia il mutex.
Quando una richiesta di blocco della riattivazione viene restituita correttamente, il thread di sospensione viene bloccato.

API SystemSuspend
L'API SystemSuspend è costituita da due interfacce. L'interfaccia HIDL viene utilizzata dai processi nativi per acquisire i wake lock, mentre l'interfaccia AIDL viene utilizzata per la comunicazione tra SystemServer e SystemSuspend.
Interfaccia HIDL ISystemSuspend
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 wake lock riceve un'istanza
IWakeLock
univoca. Questo è diverso da
/sys/power/wake_lock
, che consente a più
client di utilizzare il blocco di riattivazione con lo stesso nome. Se un client che contiene un'istanza IWakeLock
termina, il driver binder e il servizio SystemSuspend lo puliscono.
Interfaccia AIDL ISuspendControlService
ISuspendControlService è destinato all'utilizzo esclusivo da parte di SystemServer.
interface ISuspendCallback {
void notifyWakeup(boolean success);
}
interface ISuspendControlService {
boolean enableAutosuspend();
boolean registerCallback(ISuspendCallback callback);
boolean forceSuspend();
}
L'utilizzo di Android HIDL offre i seguenti vantaggi:
- Se un processo di blocco della sospensione termina, SystemSuspend può ricevere una notifica.
- Il thread responsabile della sospensione del sistema può essere richiamato.