SystemSuspend-Dienst

In Android 9 und niedriger gibt es einen Thread in libsuspend, der für die Initiierung des Systemsuspendierens verantwortlich ist. Android 10 führt eine entsprechende Funktionalität in einem SystemSuspend HIDL-Dienst ein. Dieser Dienst befindet sich im Systemabbild und wird von der Android-Plattform bereitgestellt. Die Logik von libsuspend bleibt weitgehend dieselbe, außer dass jeder Userspace-Prozess, der den Systemsuspend blockiert, mit SystemSuspend kommunizieren muss.

libsuspend und libpower

In Android 10 ersetzt der SystemSuspend-Dienst libsuspend . libpower wurde neu implementiert, um auf den SystemSuspend-Dienst anstelle von /sys/ power /wake[un]lock zu setzen, 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 verfolgt die Anzahl der ausgestellten Wakelocks mit einem Suspend-Zähler. Es gibt zwei Ausführungsthreads:

  • Der Hauptthread beantwortet Binder-Aufrufe.
  • Der Suspend- Thread steuert den Suspend des Systems.

Haupt-Bedroung

Der Hauptthread beantwortet Anfragen von Clients, neue Wake-Locks zuzuweisen, indem er den Suspend-Zähler erhöht/dekrementiert.

Thread unterbrechen

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

  1. Aus /sys/ power /wakeup_count lesen.
  2. Erwerben Sie den Mutex. Dadurch wird sichergestellt, dass der Suspend-Thread den Suspend-Zähler nicht berührt, während der Haupt -Thread versucht, ihn zu erhöhen oder zu dekrementieren. Der Hauptthread wird beim Ausgeben oder Entfernen von Wecksperren blockiert, wenn der Suspend-Zähler Null erreicht hat und der Suspend- Thread versucht, auszuführen.
  3. Warten Sie, bis der Zähler gleich Null ist.
  4. Schreiben Sie den aus /sys/ power /wakeup_count (aus Schritt 1) ​​gelesenen Wert in diese Datei. Wenn der Schreibvorgang 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. Geben Sie den Mutex frei.

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

Abbildung 1. Fadenschlaufe aufhängen

SystemSuspend-API

Die SystemSuspend-API besteht aus zwei Schnittstellen. Die HIDL-Schnittstelle wird von nativen Prozessen zum Erlangen von Wakelocks verwendet und 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 Wecksperre anfordert, erhält eine eindeutige IWakeLock Instanz. Dies unterscheidet sich von /sys/ power /wake_lock , das es mehreren Clients ermöglicht, die Wake-Sperre unter demselben Namen zu verwenden. Wenn ein Client, der eine IWakeLock Instanz hält, beendet wird, wird sie vom Binder-Treiber und dem SystemSuspend-Dienst bereinigt.

ISuspendControlService AIDL-Schnittstelle

ISuspendControlService soll nur von 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 die folgenden Vorteile:

  • Wenn ein Suspend-blockierender Prozess abbricht, kann SystemSuspend benachrichtigt werden.
  • Dem Thread, der für die Systemunterbrechung verantwortlich ist, kann ein Rückruf gegeben werden.