CodeHighlight

2017年4月26日 星期三

[Android] Build break: ERROR XXX undefined

最近案子整個大爆炸呀!

幾乎每天都在跨日大戰,腦容量整個降到一個低點。

還好這幾日應該慢慢狀況慢慢穩定下來了。

好想休假呀~~

=====================碎碎念結束=========================

前陣子在帶新案子起來的時候,過程中各個module在把好幾包code倒來倒去

某日就接到了Build break在我這邊的module:



ERROR: "msm_11ad_modinit" [drivers/net/wireless/ath/wil6210/wil6210.ko] undefined!
ERROR: "msm_11ad_dev_init" [drivers/net/wireless/ath/wil6210/wil6210.ko] undefined!
ERROR: "msm_11ad_modexit" [drivers/net/wireless/ath/wil6210/wil6210.ko] undefined!
make[2]: *** [__modpost] Error 1
make[1]: *** [modules] Error 2
make[1]: *** Waiting for unfinished jobs...

嗯,看起來應該是倒code的時候某些東西沒有跟上了吧!
看了一下,Undefined的部分是編wil6210.ko的時候。
所以這個時候就有兩條路了:

  1. 是那些東西沒有define
  2. 這個module到底有沒有要build
如果是第一種,那就是trace code的功夫了,那也就沒甚麼好說的。
會在這邊廢話,代表狀況其實是第二種。
內部查了一下,發現wil6210這個東西其實本來就沒有要build的。
那為什麼會被build進去呢?

原來在build kernel的階段,每個module會根據kconfig的內容,決定要不要build這個東西
像這次就是CONFIG_WIL6210這個值在倒code時被設起來了,
所以才會出現這樣的狀況。

解法:在Kconfig中找到CONFIG_WIL6210,拔掉它即可。

2017年4月5日 星期三

[Android] sendEmptyMessage 和 sendEmptyMessageDelayed

    最近在測試上面,有需要在Android上面針對特定功能反覆開關的需求。

本來是想說在原本的原始碼上面讓他定時反覆啟動。

不過這樣每次都要額外加code以及build code,實在是有點麻煩。

所以這邊試著寫一個簡單的APP去定時做這件事情。

不過Android APP嗎,你知道的,如果用一般的delay的話,過一下就ANR了

爬了一下Android framework的做法,後來決定用Handler thread + delay message的方法來做

概念上是宣告一個handler thread,這東西會用一個獨立的thread去聽message。

如果有人對這個handler 送message,handler可以根據不同的message,去做不同的事情。

而利用延遲訊息(delayMessage),可以達到定時去做同一件事情的效果。

這邊筆記一下Handler底下sendEmptyMessage 和sendEmptyMessageDelayed的差異。


sendEmptyMessage

原生宣告是 boolean sendEmptyMessage (int what)

顧名思義,這個function是送一個空的訊息給Handler

所以不用把東西特別包成Message型態,可以直接送一個int的值



sendEmptyMessageDelayed

原生宣告是 boolean sendEmptyMessageDelayed (int what, long delayMillis)

相較於sendEmptyMessage,他可以決定到底這個message要等多久後再送,單位是ms


下面是一個簡單的範例:



    
    private static final int NEXT_ACTION_INTERVAL_MS = 5000;                                                                                                                                                 

...

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.i(TAG, "onCreate()+");
    setContentView(R.layout.main);
    context = this;
    mWifiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
    mLock = mWifiManager.createMulticastLock(TAG);

    mHandler = new Handler(Looper.getMainLooper()) ;

    // 宣告一個按鈕,按下去後就會去sendEmptyMessage(CMD_START_TEST)給mThreadHandler
    button1 = (Button) findViewById(R.id.button1);
    button1.setOnClickListener( new OnClickListener() {
            public void onClick(View v) {
            mThreadHandler.sendEmptyMessage(CMD_START_TEST);
            result_text.setText("Start thread action");
            }
            });

...

    mThread = new HandlerThread("name");
    mThread.start();
    mThreadHandler = new Handler(mThread.getLooper()) {
        private boolean isRunning = false;
        private int mCounter = 0;
        @Override
            public void handleMessage (Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    // ** 接到CMD_START_TEST後,除了做特定的事情外。
                    // ** 並會等候NEXT_ACTION_INTERVAL_MS後再發CMD_LOOP_TEST
                    case CMD_START_TEST:
                        if (!isRunning) {
                            this.sendEmptyMessageDelayed(CMD_LOOP_TEST, NEXT_ACTION_INTERVAL_MS);
                            isRunning = true;
                            Log.e(TAG, "Start Testing!");
                            mWifiManager.startScan();
                            mCounter++;
                            result_text.setText("Repeat times: " + mCounter);
                        }
                        break;
                    case CMD_STOP_TEST:
                        isRunning = false;
                        mCounter = 0;
                        break;
                    // ** 接到CME_LOOP_TEST後,繼續相同的測試&準備下一個NEXT_ACTION_INTERVAL_MS後的message
                    case CMD_LOOP_TEST:
                        if (isRunning) {
                            mWifiManager.startScan();
                            mCounter++;
                            result_text.setText("Repeat times: " + mCounter);
                            this.sendEmptyMessageDelayed(CMD_LOOP_TEST, NEXT_ACTION_INTERVAL_MS);
                        }
                        break;
                }
            }
    };