迅為RK3588開發(fā)板是一款低功耗、高性能的處理器,適用于基于arm的PC和Edge計(jì)算設(shè)備、個(gè)人移動(dòng)互聯(lián)網(wǎng)設(shè)備等數(shù)字多媒體應(yīng)用,RK3588支持8K視頻編解碼,內(nèi)置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800萬像素ISP,內(nèi)置NPU,支持INT4/INT8/INT16/FP16混合運(yùn)算能力,支持安卓12和、Debian11、Build root、Ubuntu20和22版本登系統(tǒng)。了解更多信息可點(diǎn)擊迅為官網(wǎng)
【實(shí)驗(yàn)平臺(tái)】:迅為RK3588開發(fā)板
【內(nèi)容來源】《【北京迅為】itop-3588開發(fā)板多屏顯示手冊(cè)v1.0》
RK3588最多可以支持7個(gè)屏幕顯示,這主要取決于RK3588芯片內(nèi)置了VOP控制器,
支持四路視頻同顯或異顯,可有效提高行業(yè)定制的拓展性。本章節(jié)我們將介紹在RK3588的Android12系統(tǒng)上實(shí)現(xiàn)多屏顯示。
1.1 Android 多屏同顯
iTOP-RK3588開發(fā)板支持以下屏幕
迅為MIPI 7寸屏幕
標(biāo)準(zhǔn)HDMI屏幕(通過HDMI線連接)
迅為 LVDS 7 寸屏幕
迅為 LVDS 10.1 寸 1024*600 屏幕
迅為 LVDS 10.1 寸 1280*800 屏幕
迅為 LVDS 10.1 寸 1280*800 新屏幕
然后修改Android12源碼kernel-5.10/arch/arm64/boot/dts/rockchip/topeet_screen_lcds.dts中
的設(shè)備樹文件,如下圖所示。LVDS屏幕是MIPI通過轉(zhuǎn)接板連接顯示的,RK3588不支持LVDS顯示接口。
注:
其中#define LCD_TYPE_LVDS_10_1_1280X800_GT911和#define
LCD_TYPE_LVDS_10_1_1280X800_GT9271不同之處在于屏幕背板,可通過如下進(jìn)行區(qū)分:
#define LCD_TYPE_LVDS_10_1_1280X800_GT911
#define LCD_TYPE_LVDS_10_1_1280X800_GT9271
我們可以根據(jù)自己的需求來修改topeet_screen_choose.dtsi文件。總之,修改
topeet_screen_choose.dtsi的規(guī)律是:打開所連接的屏幕對(duì)應(yīng)的宏定義,rk3588有三個(gè)顯示通道vp0 vp1 vp2 vp3,所打開的宏定義對(duì)應(yīng)的vp通道不能重復(fù)。默認(rèn)打開對(duì)應(yīng)的宏定義為多屏同顯。
RK3588 VP和各顯示接口的連接關(guān)系如下圖所示。
1.2 Android 多屏異顯
如果要支持多屏異顯,首先要調(diào)試好雙屏或多屏都可以正常顯示,并且分別掛載在不同的vp上,可以參考上一個(gè)小節(jié)根據(jù)自己的需求打開topeet_screen_choose.dtsi設(shè)備樹中的宏定義。
默認(rèn)開啟后,多屏顯示的是同一個(gè)畫面(如果要支持雙屏或者多屏異顯,需要應(yīng)用支持異顯, 才會(huì)顯示不同的內(nèi)容)。查看當(dāng)前的屏幕顯示狀態(tài)輸入以下命令
cat /sys/kernel/debug/dri/0/summary
如果雙屏或者多屏的顯示器分辨率比例不同,比如說主屏是16:9,副屏是4:3,那么副 屏顯示的畫面會(huì)拉伸或者縮小,原因是副屏的畫面是主屏映射過去的,所以副屏上顯示的是 主屏的分辨率。如果同樣的屏幕情況下,應(yīng)用支持異顯,那么副屏?xí)@示實(shí)際正常的分辨率。
所以如果要支持雙屏或者多屏同顯并要求顯示正常,雙屏或者多屏的屏幕的分辨率比要一致。
1.2.1 指定主副屏
多屏異顯的實(shí)際應(yīng)用中,需要指定哪個(gè)是主屏,哪個(gè)是副屏。修改Android12源碼目錄下3588-android12/device/rockchip/rk3588/rk3588_s/rk3588_s.mk文件,添加如下內(nèi)容:
如果要指定MIPI屏幕為主屏,HDMI屏幕為副屏,如下設(shè)置:
PRODUCT_PROPERTY_OVERRIDES += vendor.hwc.device.primary=DSI
PRODUCT_PROPERTY_OVERRIDES += vendor.hwc.device.extend=HDMI-A
如果要指定MIPI屏幕為主屏,EDP屏幕為副屏,如下設(shè)置:
PRODUCT_PROPERTY_OVERRIDES += vendor.hwc.device.primary=DSI
PRODUCT_PROPERTY_OVERRIDES += vendor.hwc.device.extend=eDP
如果需要定義多個(gè)主副屏?xí)r,需要用逗號(hào)隔開,比如指定MIPI eDP為主屏,HDMI-A為副屏,
設(shè)置如下:
PRODUCT_PROPERTY_OVERRIDES += vendor.hwc.device.primary=DSI,eDP
PRODUCT_PROPERTY_OVERRIDES += vendor.hwc.device.extend=HDMI-A
1.2.2 異顯方案介紹
目前有兩種異顯方案分別是Android Presentation和Andorid Activity指定屏幕啟動(dòng)。
Android Presentation,需要APP應(yīng)用開發(fā)中調(diào)用相應(yīng)接口使指定的view (Presentation view是一個(gè)特殊的dialog類型view)在副屏中顯示。
Android Activity指定屏幕啟動(dòng),APP在啟動(dòng)activity時(shí)可以使用display id參數(shù)在對(duì)應(yīng)的屏幕上直接顯示。
兩者主要區(qū)別在:
1前者的acitivity需要獨(dú)立開發(fā),把需要顯示的內(nèi)容投到副屏,后者可以不需要源碼,調(diào)用命令行或者系統(tǒng)接口把第三方app的acitivity投送到副屏;
2 .前者只有一個(gè)activity在頂層,通過特殊的dialog將指定內(nèi)容顯示在副屏,后者是兩個(gè)activity分別顯示在主副屏。
接下來我們?cè)敿?xì)講述這倆種方法。
1.2.3 Android Presentation
本小節(jié)講解Android Presentation異顯方案,瑞芯微和迅為提供了使用Android Presentation編寫好的APP例程,接下來進(jìn)行測試。
1.2.3.1 ApiDemos APP
在Android12源碼中瑞芯微已經(jīng)提供了使用Presentation接口的測試APP,在源碼development/samples/ApiDemos目錄下,需要使用mm命令編譯APP。迅為提供了編譯好的 測試APP在網(wǎng)盤資料“iTOP-RK3588開發(fā)板/02_【iTOP-RK3588開發(fā)板】/12_多屏顯示配套 資料/Android/ApiDemosAPK”目錄下。
此APP源碼在Android源碼3588-android12/development/samples/ApiDemos目錄下,進(jìn)入 此目錄,輸入“mm”命令進(jìn)行編譯,如下圖所示:
然后使用adb命令安裝APP,依次點(diǎn)擊App->Activity->Presentation選項(xiàng),即可進(jìn)入Presentation調(diào)用界面。如下圖所示:
在該界面需點(diǎn)擊如下副屏的checkbox選項(xiàng),即可在副屏顯示相應(yīng)圖片。副屏HDMi屏幕顯示圖片,
1.2.3.2 Presentation sampleAPP
此APP在網(wǎng)盤資料“iTOP-RK3588開發(fā)板/02_【iTOP-RK3588開發(fā)板】/12_多屏顯示配 套資料/Android/Presentation sample”目錄下,下載此APP工程,然后用Androidstudio打開, 并編譯apk。編譯成功之后,安裝APP,APP安裝成功之后如下圖所示:
打開APP如下圖所示:
點(diǎn)擊“顯示副屏”按鈕,會(huì)在副屏顯示,如下圖所示:
APP重要知識(shí)點(diǎn)講解:
隨著用戶的需求增多,特別是對(duì)于一些Android平板電腦以及其他的一些Android智能設(shè)備可能有多個(gè)屏幕,用戶不僅想要在主屏幕上顯示內(nèi)容,同樣在第二屏幕上也要顯示想要的內(nèi)容,這樣可以達(dá)到更好的體驗(yàn)效果。Google也是不負(fù)眾望在Android4.2版本以后提供了Presentation類,可以輕松實(shí)現(xiàn)在兩塊屏幕上同時(shí)顯示不同的內(nèi)容。Presentation是一個(gè)特殊的dialog,它的目的是顯示內(nèi)容到第二屏幕。在Presentation創(chuàng)建的時(shí)候關(guān)聯(lián)一個(gè)目標(biāo)設(shè)備,確
定Presentation要顯示在那個(gè)設(shè)備上,根據(jù)這個(gè)設(shè)備的信息來配置Presentation的context和resources信息。目前系統(tǒng)提供了兩種方式來與目標(biāo)顯示屏進(jìn)行綁定。
1通過MediaRouter接口獲取并綁定:
選擇顯示presentation的設(shè)備最簡單的方法就是使用Media Router,media router服務(wù)持續(xù)追蹤在系統(tǒng)中哪個(gè)音頻、視頻線路是可用的,當(dāng)routes被選擇或者不被選擇,或者更好的顯示presentation display的線路發(fā)生改變后media router就會(huì)發(fā)送消息。所以一些應(yīng)用程序可以自動(dòng)監(jiān)視這些消息來在首選設(shè)備上顯示或取消presentation。
首選顯示presentation的設(shè)備是Media Router進(jìn)行推薦的,如果應(yīng)用想要顯示內(nèi)容在第二 屏幕上就該使用該設(shè)備。下面將給出如何使用media router在主屏的設(shè)備創(chuàng)建和顯示
presentation。
MediaRouter mediaRouter =(MediaRouter)
context.getSystemService(Context.MEDIA_ROUTER_SERVICE); MediaRouter.RouteInfo route =
mediaRouter.getSelectedRoute();
if(route !=null){
Display presentationDisplay = route.getPresentationDisplay();
if(presentationDisplay !=null){
Presentation presentation =newMyPresentation(context, presentationDisplay);
presentation.show();
}
}
根據(jù)上面代碼可以看出通過系統(tǒng)服務(wù)Media Router來選擇一個(gè)合適的route,從route中來獲取首選的display,如果display不為空就會(huì)創(chuàng)建該presentation,創(chuàng)建完成后調(diào)用presentation的show方法將該presentation顯示出來。
2通過DisplayManager接口獲取并綁定
另外一個(gè)獲取首選display的方法是直接使用display Manager來獲取。display manager服務(wù)提供方法枚舉和描述系統(tǒng)中所有的設(shè)備,包括可以顯示presentation的設(shè)備。display manager持續(xù)追蹤系統(tǒng)中所有的設(shè)備,然而,并不是所有的設(shè)備都適合顯示presentation,例如,如果 一個(gè)Activity試圖在主屏幕上顯示一個(gè)presentation,它可能會(huì)掩蓋自己的內(nèi)容,這就像在Activity上打開一個(gè)dialog一樣。
DisplayManager displayManager =(DisplayManager)
context.getSystemService(Context.DISPLAY_SERVICE); Display[] presentationDisplays
=displayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
if(presentationDisplays.length >0){
// If there is more than one suitable presentation display, then we could consider
// giving the user a choice. For this example, we simply choose the first display
// which is the one the system recommends as the preferred presentation display.
Display display = presentationDisplays[1]; // displays[1]是副屏
Presentation presentation =new MyPresentation(context, presentationDisplay);
presentation.show();
}
根據(jù)上面代碼可以看出通過系統(tǒng)服務(wù)Display Manager來獲取所有適合顯示presentation的display列表,如果獲取到了多個(gè)適合display對(duì)象,我們選擇副屏的display。最后顯示presentation。
1.2.4 Android Activity 指定屏幕啟動(dòng)
本小節(jié)講解Android Activity指定屏幕啟動(dòng)異顯方案,瑞芯微提供了使用Android Activity指定屏幕啟動(dòng)編寫好的APP例程,接下來進(jìn)行測試。
1.2.4.1 dualscreendemo APP
RK DualScreen主要區(qū)別與android presentation,在于它實(shí)現(xiàn)了應(yīng)用的派發(fā),允許廠商快速根據(jù)現(xiàn)有的app功能,進(jìn)行模塊的集成,減少開發(fā)周期和研發(fā)成本。示例代碼為DualScreenDemo.zip工程,在網(wǎng)盤資料“iTOP-RK3588開發(fā)板/02_【iTOP-RK3588開發(fā)板】/12_多屏顯示配套資料/Android/DualScreenDemo”目錄下下載。
使用Androidstudio打開此工程代碼,編譯安裝APP,安裝完成后如下所示:
打開此APP,如下所示,有三個(gè)按鈕。
第三個(gè)按鈕使用了Android Activity指定屏幕啟動(dòng),關(guān)鍵代碼如下所示,第一個(gè)和第二個(gè)按鈕使用了Presentation。
private void showSecondByActivity(Context context){
ActivityOptions options = ActivityOptions.makeBasic();
MediaRouter mediaRouter = (MediaRouter)
context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
MediaRouter.RouteInfo route =
mediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_VIDEO);
if (route != null) {
Display presentationDisplay = route.getPresentationDisplay();
options.setLaunchDisplayId(presentationDisplay.getDisplayId());
Intent intent = new Intent("android.intent.action.MUSIC_PLAYER");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent, options.toBundle());
}
}
在startActivity接口參數(shù)中設(shè)置指定屏幕的display id,Activity將在指定屏幕上直接啟動(dòng)顯示。
Activity的多顯示器支持需要設(shè)備支持。
同時(shí)application或者activity需要支持分屏屬性即或者標(biāo)簽下設(shè) 置新的屬性android:resizeableActivity="true",這個(gè)屬性在你target到Android N后android:resizeableActivity的默認(rèn)值就是true。
ActivityOptions提供兩個(gè)新函數(shù)以支持多個(gè)顯示器,分別是setLaunchDisplayId()和getLaunchDisplayId()。
setLaunchDisplayId()指定Activity在啟動(dòng)后應(yīng)顯示在哪個(gè)顯示器上。
getLaunchDisplayId()返回操作組件的當(dāng)前啟動(dòng)顯示器。
在上述代碼中使用MediaRouter接口獲取副屏的display id,同理也可以使用
DisplayManager接口獲取響應(yīng)的display id。
1.2.5 支持輸入法在副屏顯示
修改Android12源碼下的device/rockchip/common/display_settings.xml文件,如下所示:
將設(shè)置相應(yīng)屏幕shouldShowIme為true,如上配置支持輸入法在local:1的副屏上顯示。
1.2.6 副屏 DPI 設(shè)置
修改Android12源碼下的device/rockchip/common/display_settings.xml文件,
修改forcedDensity的值可以修改副屏的屏幕密度。
1.2.7 主屏幕可以觸摸,副屏不觸摸
如果想要實(shí)現(xiàn)主屏可以觸摸,副屏不用觸摸的功能。有兩種解決方式:第一種是在App應(yīng)用代碼中實(shí)現(xiàn)。第二種需要修改framework層的源碼。
第一種方式:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
第二種方式:
修改Android12源碼frameworks/native/services/inputflinger/reader/EventHub.cpp文件,屏蔽掉device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;屬性,
1.2.8 多屏異觸
多屏異觸需要指定主副屏。這里使用修改Android源碼的方式實(shí)現(xiàn)綁定副屏觸摸芯片。這樣設(shè)置以后,系統(tǒng)開機(jī)會(huì)自動(dòng)將ft5x06觸摸綁定到副屏上面去。修改文件:
frameworks/native/services/inputflinger/reader/EventHub.cpp,添加如下加紅的代碼。通過修改EventHub.cpp文件,在isExternalDeviceLocked函數(shù)中判斷設(shè)備名稱為指定的副屏設(shè)備(比如副屏的設(shè)備名稱是generic ft5x06 (79)),則返回true。
bool EventHub::isExternalDeviceLocked(Device* device) {
const char *I2C_DEVICE_NAME = "generic ft5x06 (79)";
ALOGE("input deviceis '%s' ",device->identifier.name.c_str());
if (strcmp(device->identifier.name.c_str(), I2C_DEVICE_NAME) == 0) {
return true;
}
if (device->configuration) {
bool value;
if (device->configuration->tryGetProperty(String8("device.internal"), value)) {
return !value;
}
}
return device->identifier.bus == BUS_USB || device->identifier.bus ==
BUS_BLUETOOTH;
}
這里的I2C_DEVICE_NAME需要根據(jù)實(shí)際情況添加,用戶可根據(jù)ALOGE打印信息在logcat中尋找識(shí)別到的芯片實(shí)際的名字。下面是添加了ALOGE打印信息后在logcat中得到的設(shè)備名字的截圖:
上圖中的goodix-ts和generic ft5x06 (79)即為這里使用的觸摸IC芯片的名字,將這個(gè)復(fù)制 到代碼中即可。修改完畢,重新編譯Android鏡像,用戶測試的時(shí)候可以直接使用ApiDemo APP進(jìn)行測試。
1.2.9 鼠標(biāo)異屏切換
在多屏異顯情況下,修改以下代碼使鼠標(biāo)箭頭可以移動(dòng)到需要的副屏上去進(jìn)行操作。
我們需要修改Android12源碼中
frameworks/native/services/inputflinger/reader/mapper/CursorInputMapper.cpp文件
搜索"sys.mouse.presentation",然后將下面的代碼中0改為1。
char mMousePresentation[PROPERTY_VALUE_MAX] = {1};
property_get("sys.mouse.presentation", mMousePresentation, "1");
if (strcmp(mMousePresentation, "1") == 0) {
displayId = mDisplayId;
float minX, minY, maxX, maxY;
if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
if(xCursorPosition==minX||xCursorPosition==maxX||yCursorPosition==minY||yCursorPosition==
maxY){
displayId=getPolicy()->notifyDisplayIdChanged();
mDisplayId=displayId;
}
}
}else{
displayId = mPointerController->getDisplayId();
}
然后重新編譯Android源碼,然后燒寫鏡像。
-
Android
+關(guān)注
關(guān)注
12文章
3935瀏覽量
127335 -
RK3588
+關(guān)注
關(guān)注
6文章
325瀏覽量
4311 -
迅為電子
+關(guān)注
關(guān)注
0文章
31瀏覽量
26
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論