HoneycombエミュでListPreferenceが糞動作するので追ってみた

Honeycomb SDKのプレビューが出ていたので早速Tuboroidが動作するか見てみたんですよ。
結論から言うと、ListPreferenceの動作が変わっていたために設定画面に入ると落ちました。互換性にはそれなりに自信があったので「ええー!?」とか思ったんですよ。
もしかしたらAPIの使い方を勘違いしていたのかと思いました。ところがですよ、これがですよ、公式ドキュメント読んでもさっぱり分からない。
そこで、どの部分で落ちているかを追ってみたわけですよ。


AA縮小率の設定をするところで「Resize 60% for thread a entry body which seems AA」とかSummaryのとこに表示しています。ここのロジックは前もって「Resize %s for a thread entry body which seems AA」というstringリソースを用意しておいて、表示初期段階とOnPreferenceChangeListenerが呼ばれた時にString.format使って%sのとこにgetEntry()を入れるような処理をしているわけですね。
ところがですね、例外で出てるエラーはUnknownFormatConversionExceptionで「%fなんか知らない」とか言ってるんですよ。ハァ?
意味わかんないのでAOSP最新ソースを追ってみました。
PreferenceActivityを初期化する時にListPreferenceのgetSummaryを呼んでSummaryの表示内容が更新されています。
ところがなんとListPreferenceのgetSummaryには既にsetSummaryされた文字列をString.formatのフォーマットと見なして第一引数にgetEntry()の内容を渡すというロジックが既に存在していたのです。
これは明らかにおかしい。
公式ドキュメントによるとListPreferenceのgetSummaryはオーバーライドされておらずPreferenceからそのまま継承されていると明記されているし、そもそもformat文字列とstatic文字列は全く別物であり混同することは厳禁である(インジェクションの元になる)ものなのだから、俺はたいそう混乱しました。
ちなみに、getEntry()を差し込んでくれるのは初期化時だけで設定変更時に反映してくれないという驚くべき糞実装で、これを見た瞬間に俺は支配人を呼べとtweetしたんですが、他の点でもっと論外すぎたので今となってはどうでもいいです。
さて、とりあえず公式ドキュメントが古くてコードが正しいのだろうと、AOSPコードに合わせてTuboroidを修正してみたわけですよ。
ところがですね、Honeycombエミュでちゃんと動くようになったかと思ったら、Gingerbreadエミュでは公式ドキュメント通りの動作をしてしまって思うように動作しないんですね。
すごく嫌な予感がしますよね。
AOSPのヒストリを追ってみました。
このパッチは2010/07/13にmasterにコミットされていました
いやちょっと待てよ、ますますおかしい。まず第一にこんな糞非互換パッチが半年も前に平然とコミットされるとかレビュアーは何をしていたんだということ、第二にGingerbreadより遥かに前なのに何故Gingerbreadエミュには入っていないのかということ。
更に追うと、Gigerbreadのツリーにはこのパッチは含まれておらず(ハァ?)、またエミュのListPreferenceをリフレクション使って探ってみたところgetSummaryはListPreferenceでオーバーライドされていない(=パッチが含まれていない版でビルドされている)ことが分かりました。
更にHoneycombエミュでも同様にリフレクションで探ってみると、こちらは確かにListPreferenceでオーバーライドされていました。つまりパッチを含む版でのビルドでした。
Nexus Sでも、またCyanogenModでも、このパッチはどうやら意図的に外されているようで、ListPreferenceでのオーバーライドは有りません。
ただ、当時のCyanogenModでmasterを取ってきてしまったせいかこのトラップを踏んづけてIssue投げられた形跡が有ります。
現在のCyanogenModでは外されているようです。
つまりこういうことなのでしょうか。
この非互換の糞パッチはレビュアーの目をかいくぐって半年前にmasterにコミットされ、当時のCyanogenModにIssueを発生させるという被害を出しました。
ところが何故か(……まあ糞パッチとみんなが気付いたのでしょうが……)この糞パッチはエミュでも実機でもリリースバージョンには含まれませんでした。当時は2.2がリリースされたばかりでしたが、2.2にも2.3にもブランチに含まれていません。
公式ドキュメントでもこのパッチは完全に黙殺しており、パッチのない状態でドキュメントがリリースされています。
ところが今の今になってHoneycombをビルドした際に、恐らく特に疑いもなくmasterからビルドしてしまったのでしょうね、この忘れ去られた糞パッチが混入してしまったのでしょう。
結論。
Googleはmaster上からこのパッチをrevertすべきだと思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です


reCaptcha の認証期間が終了しました。ページを再読み込みしてください。