W Androidzie 9 i starszych wersjach za inicjowanie zawieszenia systemu odpowiada wątek w libsuspend. Android 10 wprowadza równoważną funkcję w usłudze HIDL SystemSuspend.
Ta usługa znajduje się w obrazie systemu i jest obsługiwana przez platformę Android.
Logika z libsuspend
pozostaje w dużej mierze taka sama, z tym że każdy proces przestrzeni użytkownika blokujący zawieszenie systemu musi komunikować się z SystemSuspend.
libsuspend i libpower
W Androidzie 10 usługa SystemSuspend zastępuje libsuspend
. Interfejs libpower
został zaimplementowany ponownie, aby korzystać z usługi SystemSuspend zamiast /sys/power/wake[un]lock
, bez zmiany interfejsu C API.
Ten pseudokod pokazuje, jak wdrożyć funkcje acquire_wake_lock
i 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;
}
Wątki wykonawcze
Usługa SystemSuspend śledzi liczbę blokad wybudzania za pomocą licznika zawieszenia. Ma 2 wątki wykonania:
- Wątek główny odpowiada na wywołania Binder.
- Wątek suspend kontroluje zawieszenie systemu.
Wątek główny
Główny wątek odpowiada na żądania klientów dotyczące przydzielania nowych blokad wybudzania, zwiększając lub zmniejszając licznik zawieszenia.
Zawieszanie wątku
Wątek zawieszania wykonuje w pętli te czynności:
- Czytaj od
/sys/power/wakeup_count
. - Uzyskaj mutex. Dzięki temu wątek zawieszania nie modyfikuje licznika zawieszeń, gdy wątek główny próbuje go zwiększyć lub zmniejszyć. Wątek główny jest blokowany podczas wydawania lub usuwania blokad wybudzania, gdy licznik zawieszenia osiągnie zero, a wątek zawieszenia próbuje się uruchomić.
- Poczekaj, aż licznik osiągnie wartość zero.
- Zapisz w tym pliku wartość odczytaną z
/sys/power /wakeup_count
(z kroku 1). Jeśli zapis się nie powiedzie, wróć na początek pętli. - Rozpocznij zawieszanie systemu, wpisując
mem
w/sys/power/state
. - Zwolnij mutex.
Gdy żądanie blokady wybudzania zostanie zrealizowane, wątek zawieszenia zostanie zablokowany.

SystemSuspend API
Interfejs SystemSuspend API składa się z 2 interfejsów. Interfejs HIDL jest używany przez procesy natywne do uzyskiwania blokad wybudzania, a interfejs AIDL służy do komunikacji między SystemServer a SystemSuspend.
Interfejs HIDL ISystemSuspend
enum WakeLockType : uint32_t {
PARTIAL,
FULL
};
interface IWakeLock {
oneway release();
};
interface ISystemSuspend {
acquireWakeLock(WakeLockType type, string debugName)
generates (IWakeLock lock);
};
Każdy klient, który poprosi o blokadę wybudzania, otrzyma unikalną instancję IWakeLock
. Różni się to od /sys/power/wake_lock
, które umożliwia wielu klientom korzystanie z blokady wybudzania pod tą samą nazwą. Jeśli klient korzystający z instancji IWakeLock
zostanie zamknięty, sterownik Binder i usługa SystemSuspend usuną tę instancję.
Interfejs ISuspendControlService AIDL
Interfejs ISuspendControlService jest przeznaczony do używania tylko przez SystemServer.
interface ISuspendCallback {
void notifyWakeup(boolean success);
}
interface ISuspendControlService {
boolean enableAutosuspend();
boolean registerCallback(ISuspendCallback callback);
boolean forceSuspend();
}
Korzystanie z Android HIDL zapewnia te korzyści:
- Jeśli proces blokujący zawieszenie zostanie zakończony, można o tym powiadomić SystemSuspend.
- Wątek odpowiedzialny za zawieszenie systemu może otrzymać wywołanie zwrotne.