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 서비스는 정지 카운터로 발행된 wake lock의 수를 추적합니다. 여기에는 두 개의 실행 스레드가 있습니다.
- 기본 스레드는 바인더 호출에 응답합니다.
- 정지 스레드는 시스템 정지를 제어합니다.
기본 스레드
기본 스레드는 클라이언트의 요청에 응답하여 새로운 wake lock을 할당하고 정지 카운터를 늘리거나 줄입니다.
정지 스레드
정지 스레드는 루프에서 다음을 실행합니다.
/sys/power/wakeup_count
에서 읽습니다.- 뮤텍스를 가져옵니다. 그러면 기본 스레드가 증분 또는 감소를 시도하는 동안 정지 스레드가 정지 카운터를 건드리지 않습니다. 정지 카운터가 0에 도달하고 정지 스레드가 실행을 시도하는 경우에는 wake lock 발행 또는 제거 시 기본 스레드가 차단됩니다.
- 카운터가 0이 될 때까지 기다립니다.
- 1단계의
/sys/power /wakeup_count
에서 읽은 값을 이 파일에 씁니다. 쓰기에 실패하면 루프의 처음으로 돌아갑니다. mem
을/sys/power/state
에 써서 시스템 정지를 시작합니다.- 뮤텍스를 해제합니다.
wake lock 요청이 성공적으로 반환되면 정지 스레드가 차단됩니다.
SystemSuspend API
SystemSuspend API는 두 개의 인터페이스로 구성됩니다. HIDL 인터페이스는 네이티브 프로세스에서 wake lock을 획득하는 데 사용되며, 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
인스턴스를 수신합니다. 이는 여러 클라이언트가 같은 이름으로 wake lock을 사용할 수 있도록 허용하는 /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에 이를 알릴 수 있습니다.
- 시스템 정지를 담당하는 스레드가 콜백을 수신할 수 있습니다.