Servicio SystemSuspend

En Android 9 y versiones anteriores, hay un subproceso en libsuspend responsable de iniciar la suspensión del sistema. Android 10 introduce una funcionalidad equivalente en un servicio HIDL de SystemSuspend. Este servicio se encuentra en la imagen del sistema y lo proporciona la plataforma de Android. La lógica de libsuspend sigue siendo casi la misma, excepto que todos los procesos del espacio del usuario que bloquean la suspensión del sistema deben comunicarse con SystemSuspend.

libsuspend y libpower

En Android 10, el servicio SystemSuspend reemplaza a libsuspend. libpower se volvió a implementar para depender del servicio SystemSuspend en lugar de /sys/power/wake[un]lock sin cambiar la API de C.

En este pseudocódigo, se muestra cómo implementar acquire_wake_lock y 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;
}

Subprocesos de ejecución

El servicio SystemSuspend realiza un seguimiento de la cantidad de bloqueos de activación emitidos con un contador de suspensión. Tiene dos subprocesos de ejecución:

  • El subproceso main responde a las llamadas de Binder.
  • El subproceso suspend controla la suspensión del sistema.

Subproceso principal

El subproceso principal responde las solicitudes de los clientes para asignar nuevas cerraduras de activación, lo que incrementa o disminuye el contador de suspensión.

Suspender conversación

El subproceso de suspensión realiza lo siguiente en un bucle:

  1. Lee desde /sys/power/wakeup_count.
  2. Adquiere el mutex. Esto garantiza que el subproceso de suspensión no toque el contador de suspensión mientras el subproceso principal intenta incrementarlo o disminuirlo. El subproceso principal se bloquea cuando se emiten o quitan bloqueos de activación cuando el contador de suspensión llega a cero y el subproceso de suspensión intenta ejecutarse.
  3. Espera hasta que el contador sea igual a cero.
  4. Escribe el valor leído de /sys/power /wakeup_count (del paso 1) en este archivo. Si la operación de escritura falla, vuelve al principio del bucle.
  5. Para iniciar la suspensión del sistema, escribe mem en /sys/power/state.
  6. Libera la exclusión mutua.

Cuando se muestra correctamente una solicitud de bloqueo de activación, se bloquea el subproceso de suspensión.

Figura 1: Suspende el bucle de subprocesos

API de SystemSuspend

La API de SystemSuspend consta de dos interfaces. Los procesos nativos usan la interfaz HIDL para adquirir bloqueos de activación, y la interfaz AIDL se usa para la comunicación entre SystemServer y SystemSuspend.

Interfaz de HIDL de 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 un bloqueo de activación recibe una instancia única de IWakeLock. Esto es diferente de /sys/power/wake_lock, que permite que varios clientes usen el bloqueo de activación con el mismo nombre. Si se finaliza un cliente que contiene una instancia de IWakeLock, el controlador de Binder y el servicio SystemSuspend la limpian.

Interfaz del AIDL de ISuspendControlService

ISuspendControlService está diseñado para que solo lo use SystemServer.


interface ISuspendCallback {
     void notifyWakeup(boolean success);
}

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

Aprovechar Android HIDL ofrece los siguientes beneficios:

  • Si se cancela un proceso de bloqueo de suspensión, se puede notificar a SystemSuspend.
  • Se puede proporcionar una devolución de llamada al subproceso responsable de la suspensión del sistema.