Sous Android 9 et versions antérieures, il existe un thread dans libsuspend.
responsable de lancer la suspension
du système. Android 10
introduit une fonctionnalité équivalente dans
un service HIDL SystemSuspend.
Ce service se trouve dans l'image système et est diffusé par la plate-forme Android.
La logique de libsuspend
reste en grande partie la même, sauf que chaque espace utilisateur
processus bloquant la suspension du système
doit communiquer avec SystemSuspend.
libsuspend et libpower
Sous Android 10, le service SystemSuspend remplace
libsuspend
libpower
a été réimplémenté pour s'appuyer sur
le service SystemSuspend au lieu de
/sys/power/wake[un]lock
sans modifier l'API C.
Ce pseudo-code montre comment implémenter acquire_wake_lock
.
et 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;
}
Threads d'exécution
Le service SystemSuspend suit le nombre de wakelocks émis avec un compteur de suspension. Elle comporte deux threads d'exécution:
- Le thread main répond aux appels de liaison.
- Le thread suspend contrôle la suspension du système.
Thread principal
Le thread principal répond aux requêtes des clients pour allouer de nouveaux wakelocks, en augmentant/diminuant le compteur de suspension.
Suspendre le fil de discussion
Le thread de suspension effectue les opérations suivantes dans une boucle:
- Lire à partir de
/sys/power/wakeup_count
. - Procurez-vous le mutex. Cela garantit que le thread de suspension ne touche pas le compteur de suspensions pendant que le thread main tente l'incrémenter ou le décrémenter. Le thread main est bloqué lors de l'émission ou de la suppression de wakelocks lorsque le compteur de suspension a atteint zéro et que le thread suspend tente de s'exécuter.
- Attendez que le compteur soit égal à zéro.
- Écrivez la valeur lue à partir de
/sys/power /wakeup_count
(de l'étape 1) dans ce fichier. Si l'écriture échoue, revenez au début de la boucle - Lancez la suspension du système en écrivant
mem
dans/sys/power/state
- Relâchez le mutex.
Lorsqu'une requête de wakelock est renvoyée, le thread de suspension est bloqués.
API SystemSuspend
L'API SystemSuspend comprend deux interfaces. L'interface HIDL est utilisée par les processus natifs pour acquérir des wakelocks. L'interface AIDL est utilisée la communication entre SystemServer et SystemSuspend.
Interface HIDL ISystemSuspend
enum WakeLockType : uint32_t {
PARTIAL,
FULL
};
interface IWakeLock {
oneway release();
};
interface ISystemSuspend {
acquireWakeLock(WakeLockType type, string debugName)
generates (IWakeLock lock);
};
Chaque client qui demande un wakelock reçoit un
Instance IWakeLock
. Ceci est différent de
/sys/power/wake_lock
, qui permet à plusieurs
d'utiliser le wakelock sous le même nom. Si un client disposant d'un
IWakeLock
se termine, le pilote de liaison et
Le service SystemSuspend nettoie.
Interface AIDL ISuspendControlService
ISuspendControlService est destiné à être utilisé uniquement par SystemServer.
interface ISuspendCallback {
void notifyWakeup(boolean success);
}
interface ISuspendControlService {
boolean enableAutosuspend();
boolean registerCallback(ISuspendCallback callback);
boolean forceSuspend();
}
Exploiter Android HIDL offre les avantages suivants:
- Si un processus de blocage de suspension cesse de fonctionner, SystemSuspend peut en être informé.
- Le thread responsable de la suspension du système peut recevoir un rappel.