Layanan framework sederhana ini memungkinkan proses vendor menggunakan SurfaceFlinger/EGL dalam implementasi HAL, tanpa menautkan libgui. AOSP menyediakan implementasi default layanan ini, yang sepenuhnya berfungsi. Namun, vendor juga harus menerapkan API untuk menyediakan layanan ini di platform mereka.
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); }
Untuk menggunakan layanan ini:
- Mendapatkan
IAutomotiveDisplayProxyService
.android::sp<IAutomotiveDisplayProxyService> windowProxyService = IAutomotiveDisplayProxyService::getService("default"); if (windowProxyService == nullptr) { LOG(ERROR) << "Cannot use AutomotiveDisplayProxyService. Exiting."; return 1; }
- Ambil informasi tampilan aktif dari layanan untuk menentukan resolusi.
// 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; });
- Ambil
IGraphicBufferProducer
hardware (atau, HIDL GraphicBufferProducer (HGBP) dariIAutomotiveDisplayProxyService
:mGfxBufferProducer = pWindowProxy->getIGraphicBufferProducer(displayId); if (mGfxBufferProducer == nullptr) { LOG(ERROR) << "Failed to get IGraphicBufferProducer from " << "IAutomotiveDisplayProxyService."; return false; }
- Dapatkan
SurfaceHolder
dari HGBP yang diambil, dengan menggunakan APIlibbufferqueueconverter
:mSurfaceHolder = getSurfaceFromHGBP(mGfxBufferProducer); if (mSurfaceHolder == nullptr) { LOG(ERROR) << "Failed to get a Surface from HGBP."; return false; }
- Konversikan
SurfaceHolder
menjadi jendela native menggunakanlibbufferqueueconverter
API:mWindow = getNativeWindow(mSurfaceHolder.get()); if (mWindow == nullptr) { LOG(ERROR) << "Failed to get a native window from Surface."; return false; }
- Buat platform jendela EGL dengan jendela native, lalu render:
// 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; } ...
- Panggil
IAutomotiveDisplayProxyService::showWindow()
untuk menampilkan tampilan yang dirender di layar. Layanan ini memiliki prioritas tertinggi dan, karenanya, selalu mengambil kontrol layar dari pemilik saat ini:mAutomotiveDisplayProxyService->showWindow();
Lihat service.cpp
dan GlWrapper.cpp
di $ANDROID_BUILD_TOP/packages/services/Car/evs/sampleDriver/
untuk
mengetahui detail penerapan selengkapnya.
Implementasi HAL EVS memerlukan library tambahan yang ditampilkan dalam cetak tebal di bawah.
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", ],
Dukungan multi-layar
Menampilkan enumerasi perangkat dan mengambil informasi tampilan
Seperti enumerasi perangkat kamera, framework EVS menyediakan metode untuk
mengumpukan layar yang tersedia.
ID tampilan statis mengenkode ID jenis panjang, informasi
port tampilan dalam byte bawah dan Extended Display IDentification
Data
dalam bit atas.
IAutomotiveDisplayProxyService::getDisplayIdList()
menampilkan daftar
ID tampilan layar lokal fisik, yang tersedia untuk layanan EVS,
dan IEvsEnumerator::getDisplayIdList()
menampilkan daftar port
tampilan yang terhubung ke layar yang terdeteksi. ID pertama dalam daftar selalu berupa
layar utama.
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); };
Membuka perangkat layar target
Aplikasi EVS memanggil IEvsEnumerator::openDisplay_1_1() dengan nomor port tampilan target:
android::sp<IEvsDisplay> pDisplay = pEvs->openDisplay_1_1(displayId); if (pDisplay.get() == nullptr) { LOG(ERROR) << "EVS Display unavailable. Exiting."; return 1; }
Catatan: Hanya satu tampilan yang dapat digunakan dalam satu waktu, yang berarti klien EVS saat ini kehilangan tampilannya saat klien EVS lain meminta untuk membuka tampilan, meskipun keduanya tidak sama.