В Android 9 и более ранних версиях за инициирование системной приостановки отвечает поток в библиотеке libsuspend . В Android 10 аналогичная функциональность представлена в виде службы SystemSuspend на языке HIDL. Эта служба находится в образе системы и обслуживается платформой Android. Логика libsuspend в значительной степени остается той же, за исключением того, что каждый пользовательский процесс, блокирующий системную приостановку, должен взаимодействовать с SystemSuspend.
libsuspend и libpower
В Android 10 служба SystemSuspend заменяет libsuspend . libpower была переписана таким образом, чтобы полагаться на службу SystemSuspend вместо /sys/ power /wake[un]lock без изменения C API.
Этот псевдокод демонстрирует, как реализовать функции acquire_wake_lock и 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;
}
Потоки выполнения
Служба SystemSuspend отслеживает количество блокировок пробуждения, выданных с помощью счетчика приостановки. Она имеет два потока выполнения:
- Основной поток отвечает на вызовы binder.
- Поток suspend управляет приостановкой работы системы.
Основная ветка
Основной поток обрабатывает запросы клиентов на выделение новых блокировок пробуждения, увеличивая/уменьшая счетчик приостановки.
Подвесить поток
Приостановленный поток выполняет следующие действия в цикле:
- Прочитано из
/sys/ power /wakeup_count. - Захват мьютекса. Это гарантирует, что приостановленный поток не будет трогать счетчик приостановки, пока основной поток пытается увеличить или уменьшить его. Основной поток блокируется при выдаче или снятии блокировок пробуждения, когда счетчик приостановки достигает нуля и приостановленный поток пытается продолжить выполнение.
- Подождите, пока счетчик не станет равен нулю.
- Запишите в этот файл значение, считанное из
/sys/ power /wakeup_count(из шага 1). Если запись не удалась, вернитесь к началу цикла. - Запустите режим приостановки системы, записав
memпо адресу/sys/power/ state. - Освободите мьютекс.
Когда запрос на блокировку пробуждения успешно возвращается, поток, находящийся в режиме ожидания, блокируется.

API SystemSuspend
API SystemSuspend состоит из двух интерфейсов. Интерфейс HIDL используется собственными процессами для получения блокировок пробуждения, а интерфейс AIDL используется для связи между SystemServer и SystemSuspend.
Интерфейс ISystemSuspend HIDL
enum WakeLockType : uint32_t {
PARTIAL,
FULL
};
interface IWakeLock {
oneway release();
};
interface ISystemSuspend {
acquireWakeLock(WakeLockType type, string debugName)
generates (IWakeLock lock);
};
Каждый клиент, запрашивающий блокировку пробуждения, получает уникальный экземпляр IWakeLock . Это отличается от /sys/ power /wake_lock , который позволяет нескольким клиентам использовать блокировку пробуждения под одним и тем же именем. Если клиент, имеющий экземпляр IWakeLock , завершает работу, драйвер binder и служба SystemSuspend очищают его.
Интерфейс AIDL службы ISuspendControlService
Функция ISuspendControlService предназначена для использования только сервером SystemServer.
interface ISuspendCallback {
void notifyWakeup(boolean success);
}
interface ISuspendControlService {
boolean enableAutosuspend();
boolean registerCallback(ISuspendCallback callback);
boolean forceSuspend();
}
Использование Android HIDL предоставляет следующие преимущества:
- Если процесс, блокирующий приостановку, завершается с ошибкой, система SystemSuspend может получить уведомление.
- Потоку, отвечающему за приостановку системы, можно передать функцию обратного вызова.