No Android 9 e versões anteriores, há uma linha de execução em libsuspend
responsável por iniciar a suspensão do sistema. Android 10
introduz uma funcionalidade equivalente em um serviço SystemSuspend HIDL.
Esse serviço está localizado na imagem do sistema e é veiculado pela plataforma Android.
A lógica de libsuspend
permanece basicamente a mesma, com exceção de cada espaço do usuário.
o processo de bloqueio da suspensão do sistema precisa se comunicar com SystemSuspend.
libsuspend e libpower
No Android 10, o serviço SystemSuspend substitui
libsuspend
: A libpower
foi reimplementada para depender de
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;
}
Linhas de execução
O serviço SystemSuspend acompanha o número de wake locks emitidos com um contador de suspensão. Ela tem duas linhas de execução:
- A linha de execução main atende às chamadas de vinculação.
- A linha de execução de suspensão controla a suspensão do sistema.
Linha de execução principal
A linha de execução principal responde a solicitações de clientes para alocar novos wake locks, para incrementar/diminuir o contador de suspensão.
Suspender conversa
A linha de execução de suspensão realiza as seguintes ações em loop:
- Ler de
/sys/power/wakeup_count
. - Adquira o mutex. Isso garante que a linha de execução de suspensão não toque o contador de suspensão enquanto a linha de execução principal tenta incrementá-la ou diminuí-la. A linha de execução main está bloqueada emitir ou remover wake locks quando o contador de suspensão chegar a zero e a linha de execução de suspensão estiver tentando ser executada.
- Aguarde até que o contador seja igual a zero.
- Grave o valor lido de
/sys/power /wakeup_count
(da etapa 1) nesse arquivo. Se a gravação falhar, voltar ao início da repetição - Inicie a suspensão do sistema gravando
mem
no/sys/power/state
. - Solte o mutex.
Quando uma solicitação para um wake lock retorna com sucesso, a linha de execução 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.
Interface de HIDL do ISystemSuspend
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 um
IWakeLock
. Isso é diferente do
/sys/power/wake_lock
, que permite
usem o wake lock com o mesmo nome. Se um cliente com um
a instância IWakeLock
for encerrada, o driver de vinculação e
O serviço SystemSuspend faz a limpeza dele.
Interface AIDL do ISuspendControlService
O ISuspendControlService deve ser usado somente pelo SystemServer.
interface ISuspendCallback {
void notifyWakeup(boolean success);
}
interface ISuspendControlService {
boolean enableAutosuspend();
boolean registerCallback(ISuspendCallback callback);
boolean forceSuspend();
}
O uso do HIDL do Android oferece os seguintes benefícios:
- Se um processo de bloqueio de suspensão é encerrado, o SystemSuspend pode ser notificado.
- A linha de execução responsável pela suspensão do sistema pode receber um callback.