Layanan SystemSuspend

Di Android 9 dan yang lebih rendah, ada thread di libsuspend yang bertanggung jawab untuk memulai penangguhan sistem. Android 10 memperkenalkan fungsi yang setara di layanan HIDL SystemSuspend. Layanan ini terletak di image sistem dan ditayangkan oleh platform Android. Logika dari libsuspend sebagian besar tetap sama, kecuali setiap proses ruang pengguna yang memblokir penangguhan sistem harus berkomunikasi dengan SystemSuspend.

libsuspend dan libpower

Di Android 10, layanan SystemSuspend menggantikan libsuspend. libpower diimplementasikan ulang untuk mengandalkan layanan SystemSuspend, bukan /sys/power/wake[un]lock tanpa mengubah C API.

Pseudocode ini menunjukkan cara menerapkan acquire_wake_lock dan 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;
}

Thread eksekusi

Layanan SystemSuspend melacak jumlah kunci layar saat aktif yang dikeluarkan dengan penghitung penangguhan. Aplikasi ini memiliki dua thread eksekusi:

  • Thread utama menjawab panggilan binder.
  • Thread suspend mengontrol penangguhan sistem.

Thread utama

Thread utama menjawab permintaan dari klien untuk mengalokasikan wake lock baru, menambahkan/mengurangi penghitung penangguhan.

Menangguhkan rangkaian pesan

Thread yang ditangguhkan melakukan hal-hal berikut dalam satu loop:

  1. Baca dari /sys/power/wakeup_count.
  2. Dapatkan mutex. Hal ini memastikan bahwa thread penangguhan tidak menyentuh pencacah penangguhan saat thread utama mencoba menambahkan atau menguranginya. Thread utama diblokir saat mengeluarkan atau menghapus kunci layar saat penghitung penangguhan telah mencapai nol dan thread penangguhan mencoba berjalan.
  3. Menunggu hingga penghitung sama dengan nol.
  4. Tulis nilai yang dibaca dari /sys/power /wakeup_count (dari langkah 1) ke file ini. Jika operasi tulis gagal, kembali ke awal loop
  5. Mulai penangguhan sistem dengan menulis mem ke /sys/power/state.
  6. Lepaskan mutex.

Saat permintaan untuk penguncian layar saat aktif berhasil ditampilkan, thread penangguhan akan diblokir.

Gambar 1. Menangguhkan loop thread

SystemSuspend API

SystemSuspend API terdiri dari dua antarmuka. Antarmuka HIDL digunakan oleh proses native untuk mendapatkan wake lock dan antarmuka AIDL digunakan untuk komunikasi antara SystemServer dan SystemSuspend.

Antarmuka HIDL ISystemSuspend


enum WakeLockType : uint32_t {
    PARTIAL,
    FULL
};

interface IWakeLock {
    oneway release();
};

interface ISystemSuspend {
    acquireWakeLock(WakeLockType type, string debugName)
        generates (IWakeLock lock);
};

Setiap klien yang meminta penguncian layar saat aktif menerima instance IWakeLock yang unik. Ini berbeda dengan /sys/power/wake_lock, yang memungkinkan beberapa klien menggunakan penguncian layar saat aktif dengan nama yang sama. Jika klien yang memegang instance IWakeLock dihentikan, driver binder dan layanan SystemSuspend akan membersihkannya.

Antarmuka AIDL ISuspendControlService

ISuspendControlService dimaksudkan untuk hanya digunakan oleh SystemServer.


interface ISuspendCallback {
     void notifyWakeup(boolean success);
}

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

Memanfaatkan Android HIDL menawarkan manfaat berikut:

  • Jika proses pemblokiran penangguhan berhenti, SystemSuspend dapat diberi tahu.
  • Thread yang bertanggung jawab untuk penangguhan sistem dapat diberi callback.