Bu basit çerçeve hizmeti, satıcı işlemlerinin HAL uygulamalarında libgui'yi bağlamadan SurfaceFlinger/EGL kullanmasını sağlar. AOSP, tamamen işlevsel olan bu hizmetin varsayılan uygulamasını sağlar. Ancak satıcının bu hizmeti kendi platformunda sunabilmesi için API'leri de uygulaması gerekir.
package android.frameworks.automotive.display@1.0; import android.hardware.graphics.bufferqueue@2.0::IGraphicBufferProducer; interface IAutomotiveDisplayProxyService { /** * Gets an IGraphicBufferProducer instance from the service. * * @param id Target's stable display identifier * * @return igbp Returns an IGraphicBufferProducer object, that can be * converted to an ANativeWindow object. */ getIGraphicBufferProducer(uint64_t id) generates (IGraphicBufferProducer igbp); /** * Sets the ANativeWindow, which is associated with the * IGraphicBufferProducer, to be visible and to take over the display. * * @param id Target display ID * * @return success Returns true on success. */ showWindow(uint64_t id) generates (bool success); /** * Sets the ANativeWindow, which is associated with the * IGraphicBufferProducer, to be invisible and to release the control * over display. * * @param id Target display ID * * @return success Returns true on success. */ hideWindow(uint64_t id) generates (bool success); /** * Returns the stable identifiers of all available displays. * * @return ids A list of stable display identifiers. */ getDisplayIdList() generates (vec<uint64_t> ids); /** * Returns the descriptor of the target display. * * @param id Stable ID of a target display. * @return cfg DisplayConfig of the active display. * @return state Current state of the active display. */ getDisplayInfo(uint64_t id) generates (HwDisplayConfig cfg, HwDisplayState state); }
Bu hizmeti kullanmak için:
-
IAutomotiveDisplayProxyService
edinin.android::sp<IAutomotiveDisplayProxyService> windowProxyService = IAutomotiveDisplayProxyService::getService("default"); if (windowProxyService == nullptr) { LOG(ERROR) << "Cannot use AutomotiveDisplayProxyService. Exiting."; return 1; }
- Çözünürlüğü belirlemek için hizmetten etkin ekran bilgilerini alın.
// We use the first display in the list as the primary. pWindowProxy->getDisplayInfo(displayId, [this](auto dpyConfig, auto dpyState) { DisplayConfig *pConfig = (DisplayConfig*)dpyConfig.data(); mWidth = pConfig->resolution.getWidth(); mHeight = pConfig->resolution.getHeight(); ui::DisplayState* pState = (ui::DisplayState*)dpyState.data(); if (pState->orientation != ui::ROTATION_0 && pState->orientation != ui::ROTATION_180) { // rotate std::swap(mWidth, mHeight); } LOG(DEBUG) << "Display resolution is " << mWidth << " x " << mHeight; });
-
IAutomotiveDisplayProxyService
bir donanımIGraphicBufferProducer
(veya HIDL GraphicBufferProducer (HGBP)) alın:mGfxBufferProducer = pWindowProxy->getIGraphicBufferProducer(displayId); if (mGfxBufferProducer == nullptr) { LOG(ERROR) << "Failed to get IGraphicBufferProducer from " << "IAutomotiveDisplayProxyService."; return false; }
- API
libbufferqueueconverter
kullanarak alınan bir HGBP'den birSurfaceHolder
alın:mSurfaceHolder = getSurfaceFromHGBP(mGfxBufferProducer); if (mSurfaceHolder == nullptr) { LOG(ERROR) << "Failed to get a Surface from HGBP."; return false; }
- API
libbufferqueueconverter
kullanarakSurfaceHolder
yerel bir pencereye dönüştürün:mWindow = getNativeWindow(mSurfaceHolder.get()); if (mWindow == nullptr) { LOG(ERROR) << "Failed to get a native window from Surface."; return false; }
- Yerel pencereyle bir EGL pencere yüzeyi oluşturun ve ardından şunu oluşturun:
// Set up our OpenGL ES context associated with the default display mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (mDisplay == EGL_NO_DISPLAY) { LOG(ERROR) << "Failed to get egl display"; return false; } ... // Create the EGL render target surface mSurface = eglCreateWindowSurface(mDisplay, egl_config, mWindow, nullptr); if (mSurface == EGL_NO_SURFACE) { LOG(ERROR) << "eglCreateWindowSurface failed."; return false; } ...
- Oluşturulan görünümü ekranda görüntülemek için
IAutomotiveDisplayProxyService::showWindow()
öğesini çağırın. Bu hizmet en yüksek önceliğe sahiptir ve bu nedenle ekranın kontrolünü her zaman mevcut sahibinden alır:mAutomotiveDisplayProxyService->showWindow();
Daha fazla uygulama ayrıntısı için $ANDROID_BUILD_TOP/packages/services/Car/evs/sampleDriver/
adresindeki service.cpp
ve GlWrapper.cpp
bakın.
Bir EVS HAL uygulaması, aşağıda kalın harflerle gösterilen ek kütüphaneleri gerektirir.
cc_binary { name: "android.hardware.automotive.evs@1.1-sample", vendor: true, srcs: [ ... ], shared_libs: [ ... "libbufferqueueconverter", "android.hidl.token@1.0-utils", "android.frameworks.automotive.display@1.0", "android.hardware.graphics.bufferqueue@1.0", "android.hardware.graphics.bufferqueue@2.0", ],
Çoklu ekran desteği
Cihaz numaralandırmasını görüntüleyin ve ekran bilgilerini alın
Kamera cihazı numaralandırması gibi EVS çerçevesi de mevcut ekranların numaralandırılması için bir yöntem sağlar. Statik ekran tanımlayıcı, tip uzunluğunda bir tanımlayıcıyı, alt baytta ekran bağlantı noktası bilgilerini ve üst bitlerde Extended Display IDentification Data
kodlar. IAutomotiveDisplayProxyService::getDisplayIdList()
EVS hizmeti tarafından kullanılabilen fiziksel yerel ekranların ekran kimliklerinin bir listesini döndürür ve IEvsEnumerator::getDisplayIdList()
algılanan ekranların bağlı olduğu ekran bağlantı noktalarının bir listesini döndürür. Listedeki ilk kimlik her zaman birincil ekranın kimliğidir.
interface IEvsEnumerator extends @1.0::IEvsEnumerator { ... /** * Returns a list of all EVS displays available to the system * * @return displayIds Identifiers of available displays. */ getDisplayIdList() generates (vec<uint8_t> displayIds); };
Hedef görüntüleme cihazını aç
EVS uygulaması, hedef ekran bağlantı noktası numarasıyla IEvsEnumerator::openDisplay_1_1() öğesini çağırır:
android::sp<IEvsDisplay> pDisplay = pEvs->openDisplay_1_1(displayId); if (pDisplay.get() == nullptr) { LOG(ERROR) << "EVS Display unavailable. Exiting."; return 1; }
Not: Aynı anda yalnızca tek bir ekran kullanımda olabilir; bu, başka bir EVS istemcisi ekranı açma talebinde bulunduğunda, aynı olmasalar bile mevcut EVS istemcisinin ekranını kaybedeceği anlamına gelir.