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_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 サービスは、サスペンド カウンターを使用して発行されたウェイクロックの数を追跡します。これには 2 つの実行スレッドがあります。
- メインスレッドはバインダー呼び出しに応答します。
- サスペンドスレッドはシステムのサスペンドを制御します。
メインスレッド
メインスレッドはクライアントからのリクエストに応答して新しいウェイクロックを割り当て、サスペンドカウンターを増減させます。
スレッドを一時停止する
サスペンド スレッドはループ内で次の処理を実行します。
-
/sys/ power /wakeup_count
から読み取ります。 - ミューテックスを取得します。これにより、メインスレッドがサスペンド カウンタを増減させようとしている間、サスペンド スレッドがサスペンド カウンタに触れないようにすることができます。サスペンド カウンターがゼロに達し、サスペンドスレッドが実行しようとしている場合、メインスレッドはウェイクロックの発行または削除でブロックされます。
- カウンタがゼロになるまで待ちます。
-
/sys/ power /wakeup_count
(手順 1 から) から読み取った値をこのファイルに書き込みます。書き込みに失敗した場合は、ループの先頭に戻ります。 -
mem
を/sys/power/ state
に書き込むことにより、システムのサスペンドを開始します。 - ミューテックスを解放します。
wake lock のリクエストが正常に返されると、サスペンド スレッドはブロックされます。
システムサスペンド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 に通知できます。
- システムの一時停止を担当するスレッドにはコールバックを与えることができます。