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:
- Aus
/sys/ power /wakeup_count
lesen. - 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.
- Warten Sie, bis der Zähler gleich Null ist.
- 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 - Starten Sie den System-Suspend, indem Sie
mem
in/sys/power/ state
schreiben. - Geben Sie den Mutex frei.
Wenn eine Anforderung für eine Wecksperre erfolgreich zurückgegeben wird, wird der Suspend-Thread blockiert.
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.