Serviço SystemSuspend

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:

  1. Ler de /sys/power/wakeup_count.
  2. 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.
  3. Aguarde até que o contador seja igual a zero.
  4. 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
  5. Inicie a suspensão do sistema gravando mem no /sys/power/state.
  6. Solte o mutex.

Quando uma solicitação para um wake lock retorna com sucesso, a linha de execução de suspensão é bloqueado.

Figura 1. Suspender loop da linha de execução

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.