Служба SystemSuspend

В Android 9 и более ранних версиях в libsuspend есть поток, отвечающий за инициацию приостановки системы. В Android 10 аналогичная функциональность представлена ​​в службе SystemSuspend HIDL. Этот сервис находится в образе системы и обслуживается платформой Android. Логика libsuspend остается в основном такой же, за исключением того, что каждый процесс пользовательского пространства, блокирующий приостановку системы, должен взаимодействовать с SystemSuspend.

libsuspend и libpower

В Android 10 служба SystemSuspend заменяет libsuspend . libpower была переопределена, чтобы использовать службу SystemSuspend вместо /sys/ power /wake[un]lock без изменения API C.

Этот псевдокод показывает, как 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 отслеживает количество блокировок пробуждения, выпущенных с помощью счетчика приостановки. Он имеет два потока выполнения:

  • Основной поток отвечает на вызовы связующего.
  • Поток приостановки управляет приостановкой системы.

Основная тема

Основной поток отвечает на запросы клиентов о выделении новых блокировок пробуждения, увеличивая или уменьшая счетчик приостановки.

Приостановить поток

Поток приостановки выполняет в цикле следующее:

  1. Прочитайте из /sys/ power /wakeup_count .
  2. Получите мьютекс. Это гарантирует, что поток приостановки не касается счетчика приостановки, пока основной поток пытается увеличить или уменьшить его. Основной поток блокируется при выдаче или удалении блокировки пробуждения, когда счетчик приостановки достигает нуля и приостановочный поток пытается запуститься.
  3. Подождите, пока счетчик станет равным нулю.
  4. Запишите в этот файл значение, прочитанное из /sys/ power /wakeup_count (из шага 1). Если запись не удалась, вернитесь к началу цикла.
  5. Запустите приостановку системы, записав mem в /sys/power/ state .
  6. Освободите мьютекс.

Когда запрос на блокировку пробуждения успешно возвращается, поток приостановки блокируется.

Рисунок 1. Подвеска петли нити

API системной приостановки

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 , завершает работу, драйвер связывателя и служба SystemSuspend очищают его.

AIDL-интерфейс ISuspendControlService

ISuspendControlService предназначен для использования только SystemServer.


interface ISuspendCallback {
     void notifyWakeup(boolean success);
}

interface ISuspendControlService {
    boolean enableAutosuspend();
    boolean registerCallback(ISuspendCallback callback);
    boolean forceSuspend();
}

Использование Android HIDL дает следующие преимущества:

  • Если процесс блокировки приостановки завершается, SystemSuspend может быть уведомлен.
  • Потоку, ответственному за приостановку системы, может быть предоставлен обратный вызов.