灯台下暗し -カッターナイフで恐竜を腑分けした記録-

仕事で携帯向けアプリを書いて、趣味で携帯電話を買い、趣味で同人小説を書いて、何もしていません。

私見 : FOMA M1000 が不安定な理由

2007-09-29 13:56:17 | 携帯電話

以前に FOMA M1000 のことを投稿したことがありますが、なぜ FOMA M1000 が不安定なのか、思っていることを書くことにしました。

実際に Symbian OS でネイティブアプリをプログラミングしてみると、バグを作りやすいところがあるんです。

Symbian OS でのプログラミングには特徴があります。I/O の API が非同期です。

多くの方が想像する API 呼び出しは、関数を呼び出すと処理結果が戻り値で返ってくるものでしょう。

    /* 自分のコードで引数を生成します */
    arg1 = myCode1();
    arg2 = myCode2();
    /* API を呼び出します */
    err = osApi(arg, &arg2);
    /* API の処理が終了したので、
       自分のコードでエラーチェックを行って、後処理をします。 */
    if (SUCCESS == err)
    {
        myCode3(&arg2);
    }

I/O の API が非同期になる場合、API の関数はリクエスト受付だけを行い処理を行わず即座に終了します。I/O が終了すると OS がアプリの関数を呼び出します。アプリは呼び出された関数の中で後処理をします。関数が呼び出される場合、その関数のことを一般に「コールバック関数」と呼びます。

ここではコールバック関数を用いる環境での擬似コードを紹介します。

    /* OS から呼び出してもらうコールバック関数を用意します */
    void myCallback(int err)
    {
        if (SUCCESS == err)
        {
            /* 下記の arg2 はインスタンス変数等に格納しておきます */
            myCode3(&arg2);
        }
    }

    /* ここからが、上のコードでの先頭にあたります */
    arg1 = myCode1();
    arg2 = myCode2();
    /*
     * API を呼び出します
     * ここでの戻り値は「リクエストを受け付けた」という意味です
     * I/O の時間のかかる処理は後から行われます
     * 処理が終わった後に OS が呼び出すコールバック関数も登録します
     */
    err = osApi(arg, &arg2, myCallback);
    /*
     * API 関数は即座に終了するので、
     * I/O がまだ終わっていない段階で次の行のコードが呼び出されます
     * そのことを念頭に置いて API 呼び出しの後のコードを作ります
     */
    myCode4();

「何か複雑だなあ」と思われたなら、話の要点はつかんでいらっしゃいます。

「Symbian OS ではコールバック関数は使わない、アクティブオブジェクトを使う」とおっしゃるなら、その通りです。Symbian OS では、コールバックは関数を登録するではなく、C++ オブジェクトを登録してインスタンスメソッドを呼び出してもらいます。この C++ オブジェクトを「アクティブオブジェクト」と呼びます。

アクティブオブジェクトを使った擬似コードは紹介しません。C++ クラスを定義しなければならないので、面倒なんです。

アクティブオブジェクトには利点がいくつかあります。アプリ内でスレッドを使わなくても OS が別スレッドを持っていれば並行処理が可能になるので、システム全体のスレッドの数を減らせます。I/O が終わったタイミングで OS がメソッドを呼び出すので、アプリはポーリングなどの待ちをしなくてもよくなります。関数ではなくオブジェクトを作成すると、キャンセルなどのエラー処理をカプセル化できます。

アクティブオブジェクトの総合的な解説は次の記事を参照願います。

ただ、実際にアクティブオブジェクトを作成してプログラミングしてみると、バグを作りやすいです。

オブジェクトの状態遷移機械の設計を間違えると、後からコールバックが呼び出されたときに適切に反応できなくて、意図的ではないにせよ OS からの通知を無視してしまうこともあります。すると実質的には API が戻ってこなかったのと同じになるんです。

API からの戻りをアプリが無視してしまうバグが発生しやすく、しかもバグが存在するのがアプリ側である、それが FOMA M1000 が不安定な理由です。アプリ側のバグなので、ドコモ/Motorola/Symbian が解決できません。それもネイティブアプリ・サードパーティアプリの各々が不安を抱えているわけです。これでは安定しません。

あと、アクティブオブジェクトでのプログラミングはドキュメントでの説明が難しいことも問題です。SonyEricsson が提供している Bluetooth プログラミング解説のドキュメントの中に、次のようなコードがあります。

  // Use RequestStatus to indicate asynchronous completion of the service registration.
  TRequestStatus requestStatus;
  // Register the service with the Security Manager to become “visible”.
  securityManagerSubSession.RegisterService(btServiceSecurity, requestStatus);
  // Wait for the asynchronous request to complete.
  User::WaitForRequest(requestStatus);
  // Close the security settings subsession
  securityManagerSubSession.Close();
  // Close the security manager session
  btSecurityManager.Close();

このコードは実際に走らせると確実にフリーズします。1行目で TRequestStatus オブジェクトをローカル変数に確保してから2行目で API を呼び出して3行目で戻りを待っていますが、このパターンでプログラミングするとフリーズします。これはコラム "Common mis-use and abuse of Symbian OS" の1項目目にあります。

どうして動かないサンプルコードが載っているのかを想像すると、おそらくは動くコードではサンプルにならなかったのでしょう。C++ クラスを定義しなければならないのでコード量が多くなりますし、実行がシーケンシャルでないので状態遷移を把握しないと動作を把握できません。

とはいえ、動かないコードを読んで勘所を理解した後で動くコードに置き換えるというのはプログラマにとってはつらい作業です。私は上のコードで実際につまずいて、アクティブオブジェクトがなんたるかを知りました。なので、恨みの発散も兼ねて、この文書を書いています。

なお、この話は Symbian OS のプログラミングモデルの話なので、Nokia の S60 端末でも同様のはずです。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

x-jphone-uid は端末を乗り換えても同じ

2007-09-01 11:01:57 | 携帯電話

SoftBank (ソフトバンク)携帯電話でユーザ ID として認証に使う x-jphone-uid の値は、ユーザに割り当てられているのか、端末に割り当てられているのか。

実験しました。

用意するものは

  • SoftBank 3G SIM カード1枚
  • SoftBank 3G 端末2台 ... 私の場合は SoftBank 811T と Vodafone 702NK
  • CGI/PHP 等が動くウェブサーバ
  • 自作 PHP ... x-jphone-uid を確認

実験の手順は

  1. SoftBank 811T に SIM カードを挿入します
  2. My SoftBank でユーザIDを送信するよう設定します
  3. 自作 PHP で x-jphone-uid の値を確認します
  4. Vodafone 702NK に SIM カードを挿入します
  5. 自作 PHP で x-jphone-uid の値を確認します
  6. My SoftBank でユーザIDを送信しないよう設定します
  7. SoftBank 811T に SIM カードを挿入します
  8. My SoftBank でユーザIDの設定を確認します

結論から言うと、端末を乗り換えてもユーザIDの値と送信設定は同じでした。ユーザというか、回線を認識しています。

Vodafone 702NK から送信された x-jphone-uid の値は SoftBank 811T のときと同じでしたし、Vodafone 702NK でユーザIDを送信しないように設定すると SoftBank 811T でもユーザIDを送信しなくなります。

あと、おまけとして、Vodafone 702NK のブラウザでアクセスポイント「VFJP Access Internet」を使用したときは x-jphone-uid が送信されませんでした。どうもソフトバンクのサーバで値を管理・付与しているようです。

この実験は、端末を乗り換えても値が一致するという話で、偽装が不可能という話ではありません。偽装の実験はまだ考えていません。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする