SystemSuspend-Dienst

In Android 9 und niedriger ist ein Thread in libsuspend für die Initiierung des Systemstopps verantwortlich. Android 10 führt eine entsprechende Funktion in einem SystemSuspend-HIDL-Dienst ein. Dieser Dienst befindet sich im System-Image und wird von der Android-Plattform bereitgestellt. Die Logik aus libsuspend bleibt weitgehend unverändert, mit der Ausnahme, dass jeder Userspace-Prozess, der das System-Suspend blockiert, mit SystemSuspend kommunizieren muss.

libsuspend und libpower

In Android 10 wird libsuspend durch den SystemSuspend-Dienst ersetzt. libpower wurde neu implementiert, um statt /sys/power/wake[un]lock den SystemSuspend-Dienst zu verwenden, ohne die C-API zu ändern.

Dieser Pseudocode zeigt, wie acquire_wake_lock und release_wake_lock implementiert werden.


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;
}

Ausführungsthreads

Der SystemSuspend-Dienst überwacht die Anzahl der Wakelocks, die mit einem Suspend-Zähler ausgegeben werden. Es gibt zwei Ausführungsthreads:

  • Der main-Thread beantwortet Binder-Aufrufe.
  • Der Thread suspend steuert die Systemaussetzung.

Hauptthread

Der Hauptthread beantwortet Anfragen von Clients, um neue Wakelocks zuzuweisen, wodurch der Sperrzähler erhöht/dekrementiert wird.

Unterhaltung pausieren

Der Sperren-Thread führt in einer Schleife Folgendes aus:

  1. Aus /sys/power/wakeup_count lesen
  2. Erwerben Sie den Mutex. So wird sichergestellt, dass der Suspend-Thread den Suspend-Zähler nicht berührt, während der Hauptthread versucht, ihn zu erhöhen oder zu verringern. Der main-Thread wird beim Ausstellen oder Entfernen von Aufwecksperren blockiert, wenn der Aussetzungszähler null erreicht hat und der suspend-Thread ausgeführt werden soll.
  3. Warten Sie, bis der Zähler null ist.
  4. Schreibe den aus /sys/power /wakeup_count (Schritt 1) gelesenen Wert in diese Datei. Wenn das Schreiben fehlschlägt, kehren Sie zum Anfang der Schleife zurück.
  5. Starten Sie den System-Suspend, indem Sie mem in /sys/power/state schreiben.
  6. Lassen Sie den Mutex los.

Wenn eine Anfrage für eine Wakelock erfolgreich zurückgegeben wird, wird der Suspend-Thread blockiert.

Abbildung 1: Thread-Schleife anhalten

SystemAnhalten-API

Die SystemSuspend API besteht aus zwei Schnittstellen. Die HIDL-Schnittstelle wird von nativen Prozessen verwendet, um Wakelocks zu erhalten, die AIDL-Schnittstelle wird für die Kommunikation zwischen SystemServer und SystemSuspend verwendet.

ISystemSuspend HIDL-Schnittstelle


enum WakeLockType : uint32_t {
    PARTIAL,
    FULL
};

interface IWakeLock {
    oneway release();
};

interface ISystemSuspend {
    acquireWakeLock(WakeLockType type, string debugName)
        generates (IWakeLock lock);
};

Jeder Client, der eine Wakelock anfordert, erhält eine eindeutige IWakeLock-Instanz. Das unterscheidet sich von /sys/power/wake_lock, bei dem mehrere Clients die Wakelock unter demselben Namen verwenden können. Wenn ein Client, der eine IWakeLock-Instanz hält, beendet wird, werden die Ressourcen durch den Binder-Treiber und den SystemSuspend-Dienst bereinigt.

AIDL-Schnittstelle „ISuspendControlService“

ISuspendControlService darf nur vom SystemServer verwendet werden.


interface ISuspendCallback {
     void notifyWakeup(boolean success);
}

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

Die Nutzung von Android HIDL bietet folgende Vorteile:

  • Wenn ein Prozess, der das Aussetzen blockiert, beendet wird, kann SystemSuspend benachrichtigt werden.
  • Dem Thread, der für die Systemaussetzung verantwortlich ist, kann ein Rückruf zugewiesen werden.