W Androidzie 9 i starszych wersjach znajduje się wątek w bibliotece libsuspend.
odpowiedzialnym za zainicjowanie zawieszenia systemu. Android 10
Wprowadzenie analogicznej funkcji w usłudze HIDL w systemie zawieszenia systemu.
Ta usługa znajduje się w obrazie systemu i jest obsługiwana przez platformę Androida.
Logika w libsuspend
pozostaje w dużej mierze taka sama, z wyjątkiem każdej przestrzeni użytkownika.
proces blokujący zawieszenie systemu musi komunikować się z zawieszeniem systemu.
libsuspend i libpower
W Androidzie 10 usługa Zawieszanie systemu zastępuje
libsuspend
Ponownie wdrożono libpower
, aby korzystać z
zawieszenia systemu, a nie
/sys/power/wake[un]lock
bez zmiany interfejsu C API.
Ten pseudokod pokazuje, jak wdrożyć 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 wykonania
Usługa zawieszania systemu śledzi liczbę blokad uśpienia przyznawanych za pomocą licznika zawieszenia. Ma dwa wątki:
- Wątek główny odpowiada na wywołania Binder.
- Zawieszanie powoduje zawieszenie wątku w systemie.
Wątek główny
Wątek główny odpowiada na prośby klientów o przypisanie nowych blokad uśpienia, zwiększając/zmniejszając wartość licznika zawieszenia.
Zawieś wątek
Wątek zawieszania wykonuje w pętli te działania:
- Przeczytaj od:
/sys/power/wakeup_count
. - Przejęcie muteksa. Dzięki temu zawieszony wątek nie zostanie dotknięty licznik zawieszenia, gdy wątek główny próbuje wykonać możesz zwiększyć lub zmniejszyć tę wartość. Wątek główny jest zablokowany. przy uruchamianiu lub usuwaniu blokad uśpienia, gdy licznik zawieszenia wyzeruje wartość i próbuje uruchomić wątek suspend.
- Zaczekaj, aż licznik zdarzeń będzie równy zero.
- Zapisz do tego pliku wartość odczytaną z
/sys/power /wakeup_count
(z kroku 1). Jeśli zapis się nie uda, wróć na początek pętli. - Rozpocznij zawieszanie systemu, wpisując
mem
w/sys/power/state
- Zwolnij przycisk mutex.
Po zwróceniu żądania blokady uśpienia wątek zawieszenia Użytkownik został zablokowany.
Interfejs API zawieszania systemu
Interfejs Systemsusp API składa się z 2 interfejsów. Używany jest interfejs HIDL. przez natywne procesy do uzyskiwania blokad uśpienia. Interfejs AIDL jest używany do komunikacji między serwerem systemu a zawieszeniem systemu.
Interfejs ISystemZawieszenie HIDL
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 zażąda blokady uśpienia, otrzymuje unikalny identyfikator
IWakeLock
instancja. Różni się od
/sys/power/wake_lock
, która umożliwia wiele
do używania blokady uśpienia pod tą samą nazwą. Jeśli klient trzymający
Zatrzymanie działania instancji IWakeLock
, sterownik bindera i
Usługa Zawieszanie systemu wyczyści to.
Interfejs ISuspensionControlService AIDL
Parametr IsuspControlService jest przeznaczony do używania tylko przez serwer SystemServer.
interface ISuspendCallback {
void notifyWakeup(boolean success);
}
interface ISuspendControlService {
boolean enableAutosuspend();
boolean registerCallback(ISuspendCallback callback);
boolean forceSuspend();
}
Stosowanie HIDL na Androidzie zapewnia następujące korzyści:
- Jeśli proces blokowania zawiesza się, można powiadomić o tym fakcie.
- Wątek odpowiedzialny za zawieszenie systemu może otrzymać wywołanie zwrotne.