2012年6月30日土曜日

PhoneモードとTabletモードの切り分け

ICSから変更されています。
これは注目すべき変更点です。

Phone/Tabletの切り分け

PhoneWindowManagerService#setInitialDisplaySizeの処理を確認

        // SystemUI (status bar) layout policy
        int shortSizeDp = shortSize
                * DisplayMetrics.DENSITY_DEFAULT
                / DisplayMetrics.DENSITY_DEVICE;

        if (shortSizeDp < 600) {
            // 0-599dp: "phone" UI with a separate status & navigation bar
            mHasSystemNavBar = false;
            mNavigationBarCanMove = true;
        } else if (shortSizeDp < 720) {
            // 600-719dp: "phone" UI with modifications for larger screens
            mHasSystemNavBar = false;
            mNavigationBarCanMove = false;
        } else {
            // 720dp: "tablet" UI with a single combined status & navigation bar
            mHasSystemNavBar = true;
            mNavigationBarCanMove = false;
        }


ICSでは600dp以上をTabletとして扱っていました。
JBでTabletとして認識するには720dp以上が必要です。

Android 4.1で追加されたNAVIGATION_BAR_PANEL_LAYERについて

f:id:baroqueworksdev:20120701053040p:image:w240

以下の記事にて、表示レイヤーの確認を行いました。

JBの表示レイヤーについて
http://d.hatena.ne.jp/baroqueworksdev/20120630/1341084903

今回は新規追加レイヤー、NAVIGATION_BAR_PANEL_LAYERの確認です。


NAVIGATION_BAR_PANEL_LAYERの使用箇所

PhoneWindowManager#windowTypeToLayerLw()にてwindowTypeからLayerの値に変換するので、grepはTYPE_NAVIGATION_BAR_PANELで。
引っかかるのは以下の3ファイルでした。

SystemUIが使用していますね。

  • com\android\systemui\statusbar\phone\PhoneStatusBar.java
  • com\android\systemui\statusbar\tablet\TabletStatusBar.java
  • com\android\systemui\statusbar\tablet\TabletTicker.java

PhoneStatusBar.javaに焦点をあてて調査します。
TYPE_NAVIGATION_BAR_PANELを使用しているのは以下のモジュール。
BaseStatusBar#updateSearchPanel
↓
PhoneStatusBar#getSearchLayoutParams() ←★ここでWindowLayoutのパラメータとして使用

BaseStatusBar#updateSearchPanelのモジュール内で、
mSearchPanelViewというViewをWindowにaddViewしていました。

    protected void updateSearchPanel() {
        // Search Panel
        boolean visible = false;
        if (mSearchPanelView != null) {
            visible = mSearchPanelView.isShowing();
            WindowManagerImpl.getDefault().removeView(mSearchPanelView);
        }

        // Provide SearchPanel with a temporary parent to allow layout params to work.
        LinearLayout tmpRoot = new LinearLayout(mContext);
        mSearchPanelView = (SearchPanelView) LayoutInflater.from(mContext).inflate(
                 R.layout.status_bar_search_panel, tmpRoot, false);
        mSearchPanelView.setOnTouchListener(
                 new TouchOutsideListener(MSG_CLOSE_SEARCH_PANEL, mSearchPanelView));
        mSearchPanelView.setVisibility(View.GONE);

        WindowManager.LayoutParams lp = getSearchLayoutParams(mSearchPanelView.getLayoutParams());

        WindowManagerImpl.getDefault().addView(mSearchPanelView, lp);
        mSearchPanelView.setBar(this);
        if (visible) {
            mSearchPanelView.show(true, false);
        }
    }



SearchPanelViewってなんだ?


mSearchPanelViewの表示タイミングは以下のソースを参照。
com\android\systemui\statusbar\phone\PhoneStatusBar.java


    @Override
    public void showSearchPanel() {
        super.showSearchPanel();
        WindowManager.LayoutParams lp =
            (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
        lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
        WindowManagerImpl.getDefault().updateViewLayout(mNavigationBarView, lp);
    }


    private Runnable mShowSearchPanel = new Runnable() {
        public void run() {
            showSearchPanel();
        }
    };
    View.OnTouchListener mHomeSearchActionListener = new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            switch(event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (!shouldDisableNavbarGestures()) {
                    mHandler.removeCallbacks(mShowSearchPanel);
                    mHandler.postDelayed(mShowSearchPanel, mShowSearchHoldoff);
                }
            break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mHandler.removeCallbacks(mShowSearchPanel);
            break;
        }
        return false;
        }
    };

    private void prepareNavigationBarView() {
        mNavigationBarView.reorient();

        mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
        mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPanel);
        mNavigationBarView.getHomeButton().setOnTouchListener(mHomeSearchActionListener);
        updateSearchPanel();
    }



ようはHomeキーを一定時間押し続けると、SearchPanelViewが表示されます。
Viewの処理はこちらのソースを参照

\sources\android-16\com\android\systemui\SearchPanelView.java




JBの表示レイヤーについて


Android SDKのAPI 16が公開されました。
一緒にソースもDLできるので、毎度おなじみの表示レイヤーのチェックを行いました。

確認OSバージョン

Android OS 4.1 JB

表示レイヤー

OSのメジャーアップデートなので、表示レイヤーの変更点があるかどうか確認しました。
ソース
SDK\sources\android-16\com\android\internal\policy\impl
- PhoneWindowManager.java
(★ = JBにて新規追加されたレイヤー)
レイヤー名用途
2WALLPAPER_LAYER壁紙
2APPLICATION_LAYER一般アプリケーション
3PHONE_LAYER着信などの電話用
4SEARCH_BAR_LAYER検索バー
5SYSTEM_DIALOG_LAYER電源OFFダイアログなど
6TOAST_LAYERトースト表示
7PRIORITY_PHONE_LAYERSIMエラー表示など
8SYSTEM_ALERT_LAYERANRやLowバッテリー通知
9INPUT_METHOD_LAYER文字入力UI
10INPUT_METHOD_DIALOG_LAYER文字入力UIのダイアログ
11KEYGUARD_LAYERキーガード表示
12KEYGUARD_DIALOG_LAYERシャットダウン中やSIMロック表示、キーガード表示中の電源OFFダイアログなど
13SCREENSAVER_LAYERスクリーンセーバー★
14STATUS_BAR_SUB_PANEL_LAYERPhone用expandしたパネル
15STATUS_BAR_LAYERStatusBar
16STATUS_BAR_PANEL_LAYERStatusBarをexpandしたパネル
17VOLUME_OVERLAY_LAYERボリューム変更
18SYSTEM_OVERLAY_LAYERキーガードより上位に表示するシステムオーバーレイ
19NAVIGATION_BAR_LAYERナビゲーションBar
20NAVIGATION_BAR_PANEL_LAYERナビゲーションBarの上に表示するために必要なパネル(searchなど)★
21SYSTEM_ERROR_LAYERシステムエラー通知
22DRAG_LAYERドラッグ&ドロップ操作用
23SECURE_SYSTEM_OVERLAY_LAYER
24BOOT_PROGRESS_LAYERBoot中のDialog表示
25POINTER_LAYERマウスポインター
26HIDDEN_NAV_CONSUMER_LAYERFakeWindow用


大きな変更点は
  1. SCREENSAVER_LAYERの追加
  2. NAVIGATION_BAR_PANEL_LAYERの追加

NAVIGATION_BAR_PANEL_LAYERのの使用箇所はべっと調査します。