システム一時停止サービス

Android 9 以前では、 libsuspendにシステムのサスペンドの開始を担当するスレッドがあります。 Android 10 では、SystemSuspend HIDL サービスに同等の機能が導入されています。このサービスはシステム イメージ内にあり、Android プラットフォームによって提供されます。 libsuspendからのロジックは、システムサスペンドをブロックするすべてのユーザー空間プロセスが SystemSuspend と通信する必要があることを除いて、ほぼ同じままです。

libsuspend と libpower

Android 10 では、 SystemSuspend サービスがlibsuspendを置き換えます。 libpower C API を変更せずに、 /sys/ power /wake[un]lockの代わりに SystemSuspend サービスに依存するように再実装されました。

この疑似コードは、 acquire_wake_lockrelease_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 サービスは、サスペンド カウンターを使用して発行されたウェイクロックの数を追跡します。これには 2 つの実行スレッドがあります。

  • メインスレッドはバインダー呼び出しに応答します。
  • サスペンドスレッドはシステムのサスペンドを制御します。

メインスレッド

メインスレッドはクライアントからのリクエストに応答して新しいウェイクロックを割り当て、サスペンドカウンターを増減させます。

スレッドを一時停止する

サスペンド スレッドはループ内で次の処理を実行します。

  1. /sys/ power /wakeup_countから読み取ります。
  2. ミューテックスを取得します。これにより、メインスレッドがサスペンド カウンタを増減させようとしている間、サスペンド スレッドがサスペンド カウンタに触れないようにすることができます。サスペンド カウンターがゼロに達し、サスペンドスレッドが実行しようとしている場合、メインスレッドはウェイクロックの発行または削除でブロックされます。
  3. カウンタがゼロになるまで待ちます。
  4. /sys/ power /wakeup_count (手順 1 から) から読み取った値をこのファイルに書き込みます。書き込みに失敗した場合は、ループの先頭に戻ります。
  5. mem/sys/power/ stateに書き込むことにより、システムのサスペンドを開始します。
  6. ミューテックスを解放します。

wake lock のリクエストが正常に返されると、サスペンド スレッドはブロックされます。

図 1.スレッドループの一時停止

システムサスペンドAPI

SystemSuspend API は 2 つのインターフェイスで構成されます。 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);
};

wake lock を要求する各クライアントは、一意のIWakeLockインスタンスを受け取ります。これは、複数のクライアントが同じ名前でウェイクロックを使用できるようにする/sys/ power /wake_lockとは異なります。 IWakeLockインスタンスを保持しているクライアントが終了すると、バインダー ドライバーと SystemSuspend サービスによってインスタンスがクリーンアップされます。

ISuspendControlService AIDL インターフェイス

ISuspendControlService は、SystemServer によってのみ使用されることを目的としています。


interface ISuspendCallback {
     void notifyWakeup(boolean success);
}

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

Android HIDL を活用すると、次のような利点があります。

  • サスペンドをブロックしているプロセスが停止した場合、SystemSuspend に通知できます。
  • システムの一時停止を担当するスレッドにはコールバックを与えることができます。