Layanan penangguhan sistem

Di Android 9 dan lebih rendah ada utas di libsuspend yang bertanggung jawab untuk memulai penangguhan sistem. Android 10 memperkenalkan fungsionalitas yang setara dalam layanan SystemSuspend HIDL. Layanan ini terletak di citra sistem dan dilayani oleh platform Android. Logika dari libsuspend sebagian besar tetap sama, kecuali setiap proses ruang pengguna yang memblokir penangguhan sistem perlu berkomunikasi dengan SystemSuspend.

libsuspend dan libpower

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

Pseudocode ini menunjukkan bagaimana 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;
}

Benang eksekusi

Layanan SystemSuspend melacak jumlah penguncian bangun yang dikeluarkan dengan penghitung penangguhan. Ini memiliki dua utas eksekusi:

  • Utas utama menjawab panggilan pengikat.
  • Suspend thread mengontrol sistem penangguhan.

utas utama

Utas utama menjawab permintaan dari klien untuk mengalokasikan kunci bangun baru, menambah/mengurangi penghitung penangguhan.

Tangguhkan utas

Utas penangguhan melakukan hal berikut dalam satu lingkaran:

  1. Baca dari /sys/ power /wakeup_count .
  2. Dapatkan mutexnya. Ini memastikan bahwa utas penangguhan tidak menyentuh penghitung penangguhan saat utas utama mencoba menambah atau menguranginya. Utas utama diblokir saat mengeluarkan atau menghapus penguncian saat aktif ketika penghitung penangguhan telah mencapai nol dan utas penangguhan mencoba dijalankan.
  3. Tunggu sampai penghitung sama dengan nol.
  4. Tulis nilai yang dibaca dari /sys/ power /wakeup_count (dari langkah 1) ke file ini. Jika penulisan gagal, kembali ke awal loop
  5. Mulai penangguhan sistem dengan menulis mem ke /sys/power/ state .
  6. Lepaskan mutex.

Saat permintaan penguncian layar saat aktif kembali berhasil, utas penangguhan diblokir.

Gambar 1. Suspend thread loop

API Penangguhan Sistem

SystemSuspend API terdiri dari dua antarmuka. Antarmuka HIDL digunakan oleh proses asli untuk memperoleh kunci bangun 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 instans IWakeLock yang unik. Ini berbeda dari /sys/ power /wake_lock , yang memungkinkan banyak klien menggunakan penguncian layar saat aktif dengan nama yang sama. Jika klien yang memegang IWakeLock berakhir, driver pengikat dan layanan SystemSuspend membersihkannya.

Antarmuka ISuspendControlService AIDL

ISuspendControlService dimaksudkan untuk digunakan hanya 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 mati, SystemSuspend dapat diberi tahu.
  • Utas yang bertanggung jawab atas penangguhan sistem dapat diberikan panggilan balik.