DIAL 小註解

這邊的  DIAL 是指 Netflix 和 Youtube 最近在推的 DIscover And Launch 架構. 這個技術有什麼稀奇呢? 其實它是另一種把手機/平板的螢幕投影到電視大螢幕上的方法, 特別是那些支援 DIAL 的 APP 在兩個螢幕上都存在時. 雖然說我們已經有了 Wifi Display / Miracast, WIDI 可以投影任何手機或電腦畫面到電視上, 不過它們只能視為螢幕的切換,沒有動用到 TV 上的 APP.這點是主要的不同.

使用 Miracast 也不算是容易的事. 比方說, 原本手機和電視都是各自連到家中的無線 AP 上網, 但是為了要做 Miracast, 他們得要切到  的 1, 6, 11 CH 三者其中之一去進行連線.不然他們沒辦法互相發現對方. [1] 若是無線 AP 本來不是設在 1/6/11 CH, 那麼就得有從 AP 暫時斷線再連線的動作.

 

根據 Netflix 所做的比較, DIAL 可以提供簡單的連線方式 (見下圖)[2] – 假如我們先忘記有無線 AP.此處的假設是:第一個屏 (電視、機頂盒、藍光播放機的大屏) 已經有執行 APP 的能力, 而不只是一台 "非智慧型電視". 如果電視原本沒有 "智慧", 至少得接上一個轉接盒, 電視端才能具備連網、又能執行 APP 程式的條件.

那麼, 為何只要在第二個屏 (小屏) 上執行 Youtube、Netflix,就可以跳過電視上的設定, 直接播出畫面呢? 這裡面共有 3 個不同的角色 [3]. 大屏的平台提供者 (1st screen CE device deveoper), 它要能夠用正確的參數把大屏的 APP 程式跑起來,並且確保小屏的 APP 的 payload 可以送給大屏的 APP.而小屏的 APP 負責提供 payload,大屏的 APP 負責收 payload. 另外, 無論是大屏或小屏的 APP 都要先註冊 Application Name, 這樣才能確保不會把 Youtube 的內容送給 Netflix 的 APP 程式播.

根據網站上的評論 [4], DIAL 的規格是為了對抗 Apple Airplay 跨平台的優勢. 若是我 Android 手機上有個 Youtube, Android 電視端也有一個 Youtube APP, 兩者卻不能夠連動, 使用情境就不如 Apple 方便了. 然而 DIAL 只解決了連線, Miracast 只解決了 mirror; 要讓使用者完全從 "瞪小屏" 轉到大小通吃 – 例如: 讓大屏可以顯示小屏應有的操作 (如增加手機聯絡人), 而小屏本身又變身為遙控器,不顯示聯絡人編輯畫面, 這個還有賴於 "非蘋陣營" 軟體開發人員的努力.

[ref]

1. WI-FI Alliance Member Symposium 

2. DIAL

3. Details for Developers

4. The story behind DIAL: How Netflix and YouTube want to take on AirPlay

MHL 小註解

話說前幾天, 義大2:3輸兄弟的時候寫了 “DVFS 小註解", 這次是義大 6:7 輸統一, 只好來寫個 “CBUS" 轉移心情. 什麼是 CBUS (Communication BUS)呢? 它是 MHL (Mobile High-Definition Link) 裡面的新規格.MHL 的架構如下 [1].因為講到 CBUS 不可能不提 MHL, 所以標題也就順便改了.

實際上, MHL 若不是借了 HDMI 介面的平台, 恐怕也很難攻下一席之地.一個 MHL 的 source 端, 比方說: 手機, 有機會用 micro USB 裡面的 5 根 pin, 接到 HDMI sink 端的 7 根 pin (含 3 根 ground pin)來完成 MHL 的工作.由於 micro USB 和 HDMI 都是常用的介面, 因此 MHL 推廣起來應該省了不少力.它不但能夠把手機小螢幕送上電視這個大螢幕, 還順便解決了手機充電的問題, 真是一個聰明的設計. 

 TMDS (Transition-minimized differential signaling – 最小化傳輸差分訊號)主要用來傳送音視頻的資料. 在 HDMI 的規範中, 我們有 4 個 channel (通道) 可以用. 而在 MHL 裡面, [ref 2,3] 說它只有 3 個邏輯上的通道, 和一個實際上是 3 倍快的通道. 這樣一來, 高速公路比 HDMI 少了一個車道, 怎麼還是能支援到 1080@60P 和 8 聲道的 LPCM 音訊資料呢? 原來在 [1] 當中稱為 MHL 24 bits Mutiplexing, 但是在 MHL Packetpixel Multuplexing 裡面, 它還是 mux 4 個通道.

接下來看一下 VBUS. VBUS (Voltage Bus)負責供電, 在 MHL 2.0 的規格中, 它已經可以用 5V 供應 900mV 的電流. 如果只是純粹供電, 好像學問不大? 看了 Agilent 的資料 [4],需要測試的項目也包括了 VBUS 究竟是否會干擾到 CBUS (Coupling, crosstalk),以及另一端 – 遠端 (Far End)的 MHL 是否會干擾 CBUS 和 VBUS.

至於 CBUS , 顧名思義它是做通訊用的. 當 MHL 的接頭插上 sink 端的 HDMI 端, CBUS 的 1.8V 訊號下拉, 讓 sink 可以偵測到熱插拔 (hot plug). 由於 CBUS 對接到 HDMI 的 pin 19, 這根訊號本來就是做 hot plug detection 用的, 因此和 HDMI 完全相容.

除此之外, CBUS 也兼著從 sink 端讀出 EDID (Extended display identification data – 延伸顯示能力識別). 原本的 EDID 可以從額外的 I2C 介面或是 HDMI 的 DDC 通道 (Display Data Channe – HDMI pin15/DDC clock 和 pin 16/DDC data) 讀取的. 但 MHL 已經把這個訊號線精簡掉, 所以 MHL 只能從 CBUS 上獲取這些資料.同理, CEC (Consumer Electronics Control)也被歸併到 CBUS 上.

總結來說, MHL 做的事和 HDMI 幾乎差不多. 在 VBUS 和 TMDS 的部份, 軟體的人幾乎沒有什麼事情可以做,因此負責 MHL driver 等於負責 CBUS driver.

[ref]

1. New Multimedia Interface MHL: Market Status and Technology

2. Silicon Image提供可攜式產品高清連結(MHL™)技術

3. MHL简介及信号测试方法

4. MHL Test Solution Overview

DVFS 小註解

此處的 DVFS 是指 Dynamic Voltage Frequency Scaling, 藉由動態調整電壓與頻率, 以節省系統的功耗. 基本上 DFVS 有純硬體與軟硬體合作的兩種實行方式. 純硬體版就沒太多可以討論的, 大家可以去看些論文 [1-2].第一篇的重點在於有介紹 Vfb (feedback voltage), 這樣再看 [3] 的時候會比較有感覺. 而 [2] 這一篇就兼顧了 CPU 和 GPU 省電的背景說明, 這樣思考的層面會比較廣.

​在 [2] 的第三節 DVFS background 裡面說到, 如果用軟體的方法對 CPU 做 DVFS, 最常用的方法是從 timer 和 scheduler 去蒐集每個 task 用了多少時間, 會睡多久? 接下來就要預測系統未來的負荷. 預測得愈好, 演算法愈厲害, 系統當然就愈省電. 相對地, 硬體做法談不上什麼預測能力, 但是可以節省 CPU 的運算量. 嗯, 看來跑安兔兔的時候, 應該開足馬力, 並自動關閉軟體 DVFS 30 分鐘, 哈!

[圖片遺失]

上圖取材自 [2], 比較深色的箭頭就表示硬體的流程, 淺色的部份表示軟體的流程, 而軟體必須要有硬體的搭配.圖上的 CCM 表示 clock control module, 而 PMIC 表示 power management IC 或者 PMU (power management unit). 至於圖上的 DTCP, 論文中沒有提到. 在 [4] 裡面提到它代表 Dynamic Process Temperature Compensation. 也就是可以隨著偵測到溫度的不同, 去微調 DVFS 的數值.

至於 GPU 的 DVFS, 它原本就是一個相對封閉的系統, 不像 CPU 有作業系統可以擷取資料. 論文 [2] 其實是透過 CUDA 去控制 NVIDA 的 GPU.可想而知, 我們也可以用 OpenCL, renderscript 來控制其他廠家的 GPU.

​在 Linux 內核方面, 根據 [3] 的說法, DVFS 和 DPM (dynamic power management) 是不同的概念. DVFS 需要的是數組調校過的電壓與頻率, 把它儲存在一個表格之中. 當我們預期的模型發生時, 我們就拿套好的招式出招. 而 DPM 比較著重 CPU 在何種操作模式之下, 例如: stop, run, wait,…等等.根據 [5], 他們認為 DPM 努力的方向在於:

Among the present and planned activities for DPM are:

Adding support for more platforms.

Integrating dynamic power management with standby/suspend/hibernate low-power states, and extending ACPI-inspired standby support for embedded devices that feature a variety of low-power “sleep" states.

Power policy management for tightly integrated application environments on consumer electronics devices, allowing the system designer precise control over numerous platform power parameters.

Automated power policy management that automatically selects desired power parameters based on system state, such as CPU load.

Reliably suspend and resume devices actively in use at suspend time through staged calls into drivers to suspend and lockout of new requests during a suspend period.

Integrate management of platform power parameters with device requirements, scaling device power parameters or powering off devices in response to platform changes that affect operation of devices. Possibly constrain power state transitions based on the needs of devices actively in use.

Very fast application restart on resume while slower, hotplug-capable devices are rescanned.

那麼 Android 又如何實現 DVFS 呢? 在 [3] 裡面提到, freescale 的版本中, power management service 會透過 JNI (Java Native Interface) 去 call /hardware/libhardware_legacy/power/power.c, /frameworks/base/core/jni/android_os_Power.cpp, 和  /frameworks/base/service/java/com/android/server/PowerManagerService.java.bootCompleted, 真正的 driver 當然還是 Linux 級的 kernel_imxarcharmplat-mxcdvfs-core.c. 開闢放在 /sys/devices/platform/mxc_dfvs_core.0/enable.

[ref]
1. Low-Power Fast-Settling Low-Dropout Regulator Using a Digitally Assisted Voltage Accelerator for DVFS Application

2. Low-power Task Scheduling for GPU Energy Reduction

3. 飞思卡尔省电模式介绍

4. dvfs dptc dpm

5. Dynamic Power Management

accessors 小註解

accessors 指的是物件導向語言裡面的 accessor methods. 根據 [1], 它是用來返回或設定 private field 的值. 取值的時候用 get 開頭的  method (getter), 像是 public String getLotteryNumber(). 設值的時候用 set 開頭的 method (setter), 像是 public String setMyBankAccount(), 此時稱之為 mutators. 但的確也有人把 get 和 set 都混稱為 accessors [2], 所以我也就以一當二, 省掉一些文字.

顯然地, accessors 是用 public 的方法去影響 private field. 正常來說, 在使用者無感的情況下, 它可以做到 [1]:

  • change how the data is handled behind the scenes, 像是改變 method 的定義.
  • impose validation on the values that the fields are being set to, 像是修改 data 的值域.

當然, 這就造成了反對者的批判.  [Ref 2] 的作者 Allen Holub 認為, 如果需要修改 type 等等, 只需要在特定的地方操作, 不需要有個 method 把幾百幾千個 call accessors 的地方都暴露在危險之中. 故 accessors 違背了物件導向封裝的原則.

What if you need to change the accessed field's type? You also have to change the accessor's return type. You use this return value in numerous places, so you must also change all of that code. I want to limit the effects of a change to a single class definition. I don't want them to ripple out into the entire program.

Since accessors violate the encapsulation principle,…

比較不那麼義正辭嚴, 相對搞笑的批評是這個 [3], 他有十大理由使用 setter 和 getter, 但是怎麼看都有點明褒暗貶.

  1. When you realize you need to do more than just set and get the value, you don't have to change every file in the codebase.
  2. You can perform validation here.
  3. You can change the value being set.
  4. You can hide the internal representation. getAddress() could actually be getting several fields for you.
  5. You've insulated your public interface from changes under the sheets.
  6. Some libraries expect this. Reflection, serialization, mock objects.
  7. Inheriting this class, you can override default functionality.
  8. You can have different access levels for getter and setter.
  9. Lazy loading.
  10. People can easily tell you didn't use Python.

​不管正反意見如何, 總之 C#, Action Script, Javascript 都可以用 accessors. 當我們以 Javascript 寫在 HTML 裡面時, 比較沒有被陌生人引用的風險, 相對地好處較為明顯. 但 Javascript 1.8.1 開始, 硬是限制了 setter 的用法 [Ref 5,6], 而 getter 只是取值而已故不受影響.這大概是 2008 年的事.因為我正在讀的 "新書" 裡面有提到 setter/getter, 所以幫它考證一下.

{{ js_minversion_note("1.8.1", "自 JavaScript 1.8.1 起,在設定物件和陣列裡的初始化子的屬性時,不再可以呼叫 Setter。") }}

Starting in JavaScript 1.8.1, setters are no longer called when setting properties in object and array initializers.

[ref]

1. Accessors and Mutators

2. Why getter and setter methods are evil

3. Why use getters and setters?

4. Javascript Getters and Setters for localStorage

5. Getter 和 Setter 的定義

6. set

Miracast in Android 小整理

大家都知道 Android 4.2 版支持了以前叫做 WIFI Display 的 Miracast. 看了同事轉寄的網路文章 [1], 才知道 Android 連架構都配合 Miracast 做了修改.

首先考量的是, 使用者需要把手機上的畫面輸出到電視上分享給大家, 卻不能讓大家都看見他/她怎麼在鍵盤上按密碼. 所以 surfaceflinger 就不能把虛擬鍵盤或是密碼框的這一層投射出去. 換言之, 把整個 display planes  (什麼 V1, V2, OSD1, OSD2, SUB1, SUB2) 都 mix 後才輸出的那張圖, 反而不是可以公開的.

因此, surfaceflinger 裡面就多了個 display device 的抽象層.

DISPLAY_PRIMARY:  Android 手機的螢幕

DISPLAY_RXTERNAL: HDMI 設備, 如 TV

DISPLAY_VIRTUAL: WIFI Display, 即 Miracast.

1357478805_4074

對於 virtual 的裝置, Android 並不準備它的 frame buffer.從下面這段 code 中可以看出, 每一個 Display Device 在產生的時候, 都會參考 state.isVirtualDisplay 是否為真? 進而決定 hw 這個 class 的內容. Miracast 顯然就和 HDMI, 和 local 螢幕不同類. 可見得在 HDMI 以 MHL (Mobile High-Definition Link) 接電視的情況下是允許看到輸入密碼視窗的, 但 Miracast 以 WIFI 無線時不可以顯示.

1357478788_3356

其中 static_cast< sp<ISurfaceTexture>> 表示指定型別為 sp<ISurfaceTexture>, 也就是 ISurfaceTexture 的 smart pointer. Smart pointer 也是個 pointer, 它有助於在不同的地方 create 和 destroy, 因此可以靈活地運用並減少記憶體丟失 (或曰"洩漏").它的原文是:

Smart pointers ensure we properly destroy an object even if its creation and destruction are widely separated. They make functions simpler and safer by ensuring that no matter how many different exit paths exist, local objects are always cleaned up correctly. They help enforce that exactly one object owns another object at any given time, preventing both leaks and double-frees.[2]

最後 Android 做 composer 的時候, 會對每一種顯示設備 (共 mDisplays.size 種) 檢查是否 dirty (需要更新)? 並且用 hw->canDraw() 判斷能不能畫? 如果不能畫, 連 dirty 也不畫.在 2011 年的時候, 就有人抱怨過 hw->flip 為什麼在 hw->canDraw() 的前面執行 [3]? 導致 Android suspend 的時候都還在 flip. 看來 Android 是從善如流, 改為優先判斷 canDraw() 了.

1357478824_6904

[REF]

1.Android Wi-Fi Display 介紹

2.Smart Pointer Guidelines

3.Android的Suspend​