Layanan SystemSuspend

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

libsuspend dan libpower

Di Android 10, layanan SystemSuspend menggantikan libsuspend. libpower diterapkan kembali untuk mengandalkan layanan SystemSuspend alih-alih /sys/power/wake[un]lock tanpa mengubah C API.

Kode semu ini menunjukkan cara mengimplementasikan 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 penguncian layar saat aktif yang dikeluarkan penghitung penangguhan. Kode ini memiliki dua thread eksekusi:

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

Thread utama

Thread utama menjawab permintaan klien untuk mengalokasikan penguncian layar saat aktif yang baru, menambah/mengurangi penghitung penangguhan.

Menangguhkan rangkaian pesan

Thread yang ditangguhkan akan melakukan hal berikut dalam satu loop:

  1. Baca dari /sys/power/wakeup_count.
  2. Dapatkan mutex. Hal ini memastikan bahwa thread yang ditangguhkan tidak menyentuh penghitung penangguhan saat thread utama mencoba menambah atau menguranginya. Thread utama diblokir tentang mengaktifkan atau menghapus penguncian layar saat aktif saat penghitung penangguhan mencapai nol dan thread penangguhan mencoba dijalankan.
  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.

Ketika permintaan untuk penguncian layar saat aktif berhasil dikembalikan, thread penangguhan akan diblokir.

Gambar 1. Menangguhkan thread loop

API SystemSuspend

SystemSuspend API terdiri dari dua antarmuka. Antarmuka HIDL digunakan oleh proses asli untuk memperoleh penguncian layar saat aktif 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. Hal ini berbeda dengan /sys/power/wake_lock, yang memungkinkan beberapa klien untuk menggunakan penguncian layar saat aktif dengan nama yang sama. Jika klien yang memegang Instance IWakeLock dihentikan, driver binder dan SystemSuspend membersihkannya.

Antarmuka AIDL ISuspendControlService

ISuspendControlService ditujukan untuk digunakan hanya oleh SystemServer.


interface ISuspendCallback {
     void notifyWakeup(boolean success);
}

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

Memanfaatkan HIDL Android menawarkan manfaat berikut:

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