No Android 9 e inferior há um thread em libsuspend responsável por iniciar a suspensão do sistema. O Android 10 apresenta uma funcionalidade equivalente em um serviço SystemSuspend HIDL. Este serviço está localizado na imagem do sistema e é servido pela plataforma Android. A lógica de libsuspend
permanece basicamente a mesma, exceto que cada processo de espaço de usuário que bloqueia a suspensão do sistema precisa se comunicar com SystemSuspend.
libsuspender e libpower
No Android 10, o serviço SystemSuspend substitui libsuspend
. libpower
foi reimplementado para contar com o serviço SystemSuspend em vez de /sys/ power /wake[un]lock
sem alterar a API C.
Este pseudocódigo mostra como implementar 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;
}
Tópicos de execução
O serviço SystemSuspend mantém o controle do número de wake locks emitidos com um contador de suspensão. Possui duas threads de execução:
- O encadeamento principal responde às chamadas do fichário.
- O thread de suspensão controla a suspensão do sistema.
Tópico principal
A thread principal responde a solicitações de clientes para alocar novos wake locks, incrementando/diminuindo o contador de suspensão.
Suspender tópico
O thread de suspensão executa o seguinte em um loop:
- Leia de
/sys/ power /wakeup_count
. - Adquira o mutex. Isso garante que o thread de suspensão não toque no contador de suspensão enquanto o thread principal está tentando incrementá-lo ou decrementá-lo. O encadeamento principal é bloqueado ao emitir ou remover wake locks quando o contador de suspensão atingiu zero e o encadeamento de suspensão está tentando ser executado.
- Aguarde até que o contador seja igual a zero.
- Grave o valor lido de
/sys/ power /wakeup_count
(da etapa 1) neste arquivo. Se a gravação falhar, retorne ao início do loop - Inicie a suspensão do sistema gravando
mem
em/sys/power/ state
. - Solte o mutex.
Quando uma solicitação de wake lock retorna com sucesso, o thread de suspensão é bloqueado.

API SystemSuspend
A API SystemSuspend consiste em duas interfaces. A interface HIDL é usada por processos nativos para adquirir wake locks e a interface AIDL é usada para comunicação entre SystemServer e SystemSuspend.
ISystemSuspend interface HIDL
enum WakeLockType : uint32_t {
PARTIAL,
FULL
};
interface IWakeLock {
oneway release();
};
interface ISystemSuspend {
acquireWakeLock(WakeLockType type, string debugName)
generates (IWakeLock lock);
};
Cada cliente que solicita um wake lock recebe uma instância IWakeLock
exclusiva. Isso é diferente de /sys/ power /wake_lock
, que permite que vários clientes usem o wake lock com o mesmo nome. Se um cliente que mantém uma instância IWakeLock
encerrado, o driver do binder e o serviço SystemSuspend o limparão.
Interface AIDL ISuspendControlService
ISuspendControlService destina-se a ser usado apenas pelo SystemServer.
interface ISuspendCallback {
void notifyWakeup(boolean success);
}
interface ISuspendControlService {
boolean enableAutosuspend();
boolean registerCallback(ISuspendCallback callback);
boolean forceSuspend();
}
Aproveitar o Android HIDL oferece os seguintes benefícios:
- Se um processo de bloqueio de suspensão for interrompido, o SystemSuspend poderá ser notificado.
- A thread responsável pela suspensão do sistema pode receber um retorno de chamada.