2008-01-31

どこからサスペンドさせるか?

Use10Keyサスペンド機能を修正しています。
 
まずはUse10Key v0.9でサスペンドさせた場合、
  • 電話が着信するとサスペンドが解除されて通話可能
  • 電話が終わると即座にサスペンドに戻る
    RfLedRestrictorによるLEDの消灯不可、その後の着信で問題発生
 
対してKeyLockSuspenderでサスペンドさせた場合、
  • 電話が着信するとサスペンドが解除されて通話可能
  • 電話が終わるとサスペンドに復帰
    LEDの消灯はできないが、その後の着信は問題なし
 
この致命的な差はどこから来るのでしょうか?
確認のためにUse10Keyと同じ方法でサスペンドさせるだけのプログラムを作ってみました。
 
結果、
  • 電話が着信するとサスペンドが解除されて通話可能
  • 電話が終わるとそのまま(サスペンドに戻らず)
 
どうやら電話が終わってから即座にサスペンドに戻るのはUse10Keyが電話アプリを乗っ取っている副作用のようなものだったみたいですね。
 
それならばと /klforceオプションで使っているSystemPowerStateの監視も組み込んでみました。
かなり端折っていますが、要はバックライトがついたらサスペンドさせています。
HANDLE  hPowerMsgQ      = NULL,
        hPowerNotify    = NULL;
DWORD   dwPowerMsgSize  = sizeof(POWER_BROADCAST) + (MAX_PATH * sizeof(TCHAR));

MSGQUEUEOPTIONS mqo     = {0};
mqo.dwSize              = sizeof(MSGQUEUEOPTIONS); 
mqo.dwFlags             = MSGQUEUE_NOPRECOMMIT;
mqo.dwMaxMessages       = 4;
mqo.cbMaxMessage        = dwPowerMsgSize;
mqo.bReadAccess         = TRUE;              

hPowerMsgQ = CreateMsgQueue(NULL, &mqo);
hPowerNotify = RequestPowerNotifications(hPowerMsgQ, PBT_TRANSITION);

while (WAIT_OBJECT_0 == WaitForSingleObject(hPowerMsgQ, INFINITE)) {
    DWORD               dwRead  = 0,
                        dwFlags = 0;
    PPOWER_BROADCAST    pPBCast = NULL;
    
    pPBCast = (PPOWER_BROADCAST)malloc(dwPowerMsgSize);
    if (pPBCast) {
        while (ReadMsgQueue(hPowerMsgQ, pPBCast, dwPowerMsgSize, &dwRead, 0, &dwFlags)) {
            if (PBT_TRANSITION == pPBCast->Message && 
                POWER_STATE(pPBCast->Flags) & POWER_STATE_BACKLIGHTON
            ) {
                // 画面が点灯したら即座にサスペンド
                SetSystemPowerState(NULL, POWER_STATE_SUSPEND, 0);
            }
        }
        free(pPBCast);
    }
}
 
結果は、
  • 電話が着信するとサスペンドが解除...と思いきやすぐにサスペンドに移行
    その後の電話着信不可
電話アプリ内から呼び出していた場合と違って通話中でもサスペンドしてしまうんですね。 仕方がないので、通話中だった場合は通話が終わるのを待機するようにすることで ほぼ期待通りの動作をしてくれました。
 
結論としては Use10Keyの一部としてサスペンドを組み込むことは難しそうです。
別アプリにした場合も、電話アプリの中からいちいちCreateProcess()して問題ないのかどうか悩みどころですね。
 

0 件のコメント: