You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
771 lines
24 KiB
771 lines
24 KiB
/*
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd.. 2016-2019. All rights reserved.
|
|
* Description: bootvideo ui controls
|
|
*/
|
|
|
|
#include "BootvideoUI.h"
|
|
|
|
#include <fcntl.h>
|
|
#include <semaphore.h>
|
|
#include <android/bitmap.h>
|
|
#include <binder/IServiceManager.h>
|
|
#include <cutils/klog.h>
|
|
#include <utils/Log.h>
|
|
#include <utils/SystemClock.h>
|
|
#include <sys/mman.h>
|
|
#include <system/window.h>
|
|
|
|
#include "BootvideoConfiger.h"
|
|
|
|
#undef LOG_TAG
|
|
#define LOG_TAG "BootVideo"
|
|
|
|
namespace android {
|
|
using std::string;
|
|
using std::unique_ptr;
|
|
using std::make_unique;
|
|
using namespace dolgles;
|
|
|
|
const string BaseView::VIEW_PNG_PATH = "/system/product/etc/";
|
|
const string MuteView::MUTE_PNG_NAME = "boot_video_mute.png";
|
|
const string VolumeBarView::VOLUME_PNG_NAME = "boot_video_panel.png";
|
|
const string CountDownView::COUNTDOWN_BG_NAME = "boot_video_count_bg.png";
|
|
const string CountDownView::COUNTDOWN_CH_NAME = "boot_video_count_ch.png";
|
|
const string CountDownView::COUNTDOWN_EN_NAME = "boot_video_count_en.png";
|
|
|
|
pthread_mutex_t g_mtxView = PTHREAD_MUTEX_INITIALIZER;
|
|
pthread_mutex_t g_mtxFinish = PTHREAD_MUTEX_INITIALIZER;
|
|
pthread_mutex_t g_mtxReady = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
Mutex g_mtxSideBand;
|
|
Condition g_mCdtSideBand;
|
|
|
|
static sem_t g_uiLock;
|
|
static bool InitUiLock()
|
|
{
|
|
if (sem_init(&g_uiLock, 0, 0) < 0) {
|
|
ALOGE("InitUiLock: create g_uiLock semaphore failure");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
static void DestroyUiLock()
|
|
{
|
|
sem_destroy(&g_uiLock);
|
|
}
|
|
static void WaitUiLock()
|
|
{
|
|
if (sem_wait(&g_uiLock) < 0) {
|
|
ALOGE("WaitUiLock: waiting g_uiLock semaphore failure");
|
|
}
|
|
}
|
|
static bool PostUiLock()
|
|
{
|
|
if (sem_post(&g_uiLock) < 0) { // sem_post to release lock
|
|
ALOGE("PostUiLock: post g_uiLock semaphore failure");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
BootvideoUI::BootvideoUI() : isGlesReady(false)
|
|
{
|
|
}
|
|
BootvideoUI::~BootvideoUI()
|
|
{
|
|
}
|
|
void BootvideoUI::onFirstRef()
|
|
{
|
|
run("BootvideoUI", ANDROID_PRIORITY_DISPLAY);
|
|
return;
|
|
}
|
|
|
|
status_t BootvideoUI::readyToRun()
|
|
{
|
|
// wait surface flinger start
|
|
WaitSurfaceFlinger();
|
|
// create surface
|
|
bool isSuc = CreateSurface();
|
|
if (!isSuc) {
|
|
ALOGE("CreateSurface: surface create failure");
|
|
return NO_ERROR;
|
|
}
|
|
// set player surface sideband
|
|
InitSurfacePlayer();
|
|
// init ui surface of libgles
|
|
InitSurfaceUI();
|
|
// set ready succes
|
|
SetUIReady();
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
bool BootvideoUI::WaitSurfaceFlinger() const
|
|
{
|
|
int waitCount = 0;
|
|
const int waitRetries = 10; // wait retries is 10
|
|
const int waitDelayUs = 50000; // wait 50ms
|
|
char propertyValue[PROPERTY_VALUE_MAX] = {0};
|
|
|
|
property_get("init.svc.surfaceflinger", propertyValue, nullptr);
|
|
while (strncmp(propertyValue, "running", strlen("running")) != 0) {
|
|
if (((++waitCount) % waitRetries) == 0) {
|
|
ALOGI("WaitSurfaceFlinger: retry[%d]", waitCount);
|
|
}
|
|
usleep(waitDelayUs);
|
|
property_get("init.svc.surfaceflinger", propertyValue, nullptr);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
int BootvideoUI::GetDisplayOrientation() const
|
|
{
|
|
return surface->GetDisplayOrientation();
|
|
}
|
|
|
|
bool BootvideoUI::CreateSurface()
|
|
{
|
|
#if PLATFORM_SDK_VERSION <= __ANDROID_API_Q__
|
|
surface = new SurfaceQverUI();
|
|
#else
|
|
surface = new SurfaceSverUI();
|
|
#endif
|
|
surface->CreateSurface();
|
|
surfaceW = surface->surfaceW;
|
|
surfaceH = surface->surfaceH;
|
|
return true;
|
|
}
|
|
|
|
sp<IGraphicBufferProducer> BootvideoUI::GetSideBand() const
|
|
{
|
|
Mutex::Autolock autoLock(g_mtxSideBand);
|
|
if (surfacePlayer == nullptr) {
|
|
g_mCdtSideBand.wait(g_mtxSideBand);
|
|
}
|
|
if (surfacePlayer != nullptr) {
|
|
return surfacePlayer->getIGraphicBufferProducer();
|
|
} else {
|
|
ALOGE("GetSideBand: surfacePlayer is NULL");
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
bool BootvideoUI::InitSurfacePlayer()
|
|
{
|
|
Mutex::Autolock autoLock(g_mtxSideBand);
|
|
surfacePlayer = surface->controlPlayer->getSurface();
|
|
g_mCdtSideBand.signal();
|
|
return true;
|
|
}
|
|
|
|
bool BootvideoUI::InitSurfaceUI()
|
|
{
|
|
// get Surface
|
|
surfaceUi = surface->controlUi->getSurface();
|
|
|
|
// set buffer count
|
|
int ret = native_window_set_buffer_count(surfaceUi.get(), NATIVE_WINDOW_BUFFER_COUNT);
|
|
ALOGE("InitSurfaceUI: native_window_set_buffer_count(%d)", ret);
|
|
|
|
// create DolGLDrawSurface
|
|
glesSurface = make_unique<DolGLDrawSurface>();
|
|
if (glesSurface == nullptr) {
|
|
ALOGE("InitSurfaceUI: glesSurface is NULL");
|
|
return false;
|
|
}
|
|
|
|
glesSurface->DolCreateGLContext();
|
|
|
|
// init DolGLES
|
|
ret = glesSurface->Init(DOL_ENDABLE_DRAW_TEXT | DOL_ENDABLE_BLIT | DOL_ENDABLE_DISPLAY_BITMAP |
|
|
DOL_ENDABLE_DRAW_RECT | DOL_ENDABLE_DRAW_ROUND | DOL_ENDABLE_DISPLAY_FBO | DOL_ENDABLE_FBO);
|
|
if (ret != DOL_NO_ERROR) {
|
|
ALOGE("InitSurfaceUI: init DolGLES failure(%d)", ret);
|
|
return false;
|
|
}
|
|
|
|
// Load font lib
|
|
ret = glesSurface->DolLoadFont(TEXT_FONT_PATH, TEXT_FONT_SIZE);
|
|
if (ret != DOL_NO_ERROR) {
|
|
ALOGE("InitSurfaceUI: load font lib failure(%d)", ret);
|
|
return false;
|
|
}
|
|
|
|
ret = glesSurface->DolConnectWindowSurface(surfaceUi.get());
|
|
if (ret != DOL_NO_ERROR) {
|
|
ALOGE("InitSurfaceUI: create GLWindowSurface failure(%d)", ret);
|
|
return false;
|
|
}
|
|
|
|
ALOGI("InitSurfaceUI: init DolGLES succes");
|
|
return true;
|
|
}
|
|
|
|
void BootvideoUI::Release()
|
|
{
|
|
// free gles
|
|
if (glesSurface != nullptr) {
|
|
glesSurface->DolDestoryGLContext();
|
|
glesSurface.reset();
|
|
glesSurface = nullptr;
|
|
}
|
|
// free native
|
|
surfacePlayer.clear();
|
|
surfaceUi.clear();
|
|
surface->controlPlayer.clear();
|
|
surface->controlUi.clear();
|
|
}
|
|
|
|
bool BootvideoUI::threadLoop()
|
|
{
|
|
auto configer = make_unique<BootvideoConfiger>();
|
|
if (!configer->IsFeature(BootvideoConfiger::PROPERTY_EN_UI)) {
|
|
ALOGE("threadLoop: ui feature is unable of config.xml");
|
|
return false;
|
|
}
|
|
// init lock of ui
|
|
InitUiLock();
|
|
// draw view
|
|
const int waitDelayUs = 200000; // wait 200ms
|
|
bool isEnableMute = configer->IsFeature(BootvideoConfiger::PROPERTY_EN_VOLUMEMUTE);
|
|
bool isEnableVolume = configer->IsFeature(BootvideoConfiger::PROPERTY_EN_VOLUMEBAR);
|
|
bool isEnableCountDown = configer->IsFeature(BootvideoConfiger::PROPERTY_EN_COUNTDOWN);
|
|
muteView = new MuteView(surfaceW, surfaceH, surfaceScale);
|
|
volumeView = new VolumeBarView(surfaceW, surfaceH, surfaceScale);
|
|
countView = new CountDownView(surfaceW, surfaceH, surfaceScale);
|
|
muteView->InitView();
|
|
volumeView->InitView();
|
|
countView->InitView();
|
|
CheckViewRefresh(waitDelayUs, isEnableMute, isEnableVolume, isEnableCountDown);
|
|
muteView = nullptr;
|
|
volumeView = nullptr;
|
|
countView = nullptr;
|
|
// release resource then return
|
|
Release();
|
|
// destory tick of sem
|
|
DestroyUiLock();
|
|
return false;
|
|
}
|
|
|
|
void BootvideoUI::CheckViewRefresh(int waitDelayUs, bool isEnableMute, bool isEnableVolume, bool isEnableCountDown)
|
|
{
|
|
while (!CheckExit()) {
|
|
usleep(waitDelayUs);
|
|
WaitUiLock();
|
|
if (isEnableMute) {
|
|
muteView->DrawView(glesSurface);
|
|
}
|
|
if (isEnableVolume) {
|
|
volumeView->DrawView(glesSurface);
|
|
}
|
|
if (isEnableCountDown) {
|
|
countView->DrawView(glesSurface);
|
|
}
|
|
// refresh ui surface
|
|
int ret = glesSurface->DolRefreshOnSrceen();
|
|
if (ret != DOL_NO_ERROR) {
|
|
ALOGE("threadLoop: DolRefreshOnSrceen failure(%d)", ret);
|
|
}
|
|
}
|
|
ALOGE("CheckViewRefresh: finished");
|
|
}
|
|
|
|
// create bitmap and decode png file
|
|
bool BaseView::DecodePNG(DolBitmapInfo &bitmapInfo, const string path)
|
|
{
|
|
char png_header[HEAD_BYTES];
|
|
png_structp png_ptr;
|
|
png_infop info_ptr;
|
|
char trustPath[PATH_MAX] = {0};
|
|
|
|
if (realpath(path.c_str(), trustPath) == NULL) {
|
|
ALOGE("DecodePNG: path is not canonical %s", path.c_str());
|
|
return false;
|
|
}
|
|
// open file and test for it being a png
|
|
FILE *file = fopen(trustPath, "rb");
|
|
if (file == nullptr) {
|
|
ALOGE("DecodePNG: open the png file(%s) failure", path.c_str());
|
|
return false;
|
|
}
|
|
fread(png_header, 1, HEAD_BYTES, file);
|
|
if (png_sig_cmp((png_bytep)png_header, 0, HEAD_BYTES)) {
|
|
ALOGE("DecodePNG: %s not a png file", path.c_str());
|
|
fclose(file);
|
|
return false;
|
|
}
|
|
// initialise structures for reading a png file
|
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
|
if (png_ptr == nullptr) {
|
|
ALOGE("DecodePNG: %s png_ptr create failure", path.c_str());
|
|
fclose(file);
|
|
return false;
|
|
}
|
|
info_ptr = png_create_info_struct(png_ptr);
|
|
// I/O initialisation methods
|
|
png_init_io(png_ptr, file);
|
|
png_set_sig_bytes(png_ptr, HEAD_BYTES); // Required
|
|
// read png info and pixel
|
|
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0);
|
|
unsigned int width = 0;
|
|
unsigned int height = 0;
|
|
png_get_IHDR(png_ptr, info_ptr, &width, &height, nullptr, nullptr, nullptr, nullptr, nullptr);
|
|
ALOGD("DecodePNG: the png file(%s) is %d * %d", trustPath, width, height);
|
|
// get png rows
|
|
png_bytep* row_pointers = png_get_rows(png_ptr, info_ptr);
|
|
if (row_pointers == nullptr) {
|
|
ALOGE("DecodePNG: png_get_rows failure, row_pointers is NULL");
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
|
fclose(file);
|
|
return false;
|
|
}
|
|
// malloc pixel, pixel has rgba(4 byte)
|
|
char* rgba = nullptr;
|
|
if ((width <= PNG_MAX_PIXEL) && (height <= PNG_MAX_PIXEL)) {
|
|
const unsigned int rgbaSize = width * height * RGBA_BYTES;
|
|
rgba = static_cast<char* >(malloc(rgbaSize));
|
|
}
|
|
if (rgba == nullptr) {
|
|
ALOGE("DecodePNG: malloc bits(%d*%d*4) of the png file(%s) failure", width, height, path.c_str());
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
|
fclose(file);
|
|
return false;
|
|
}
|
|
unsigned int pos = 0;
|
|
const unsigned int maxRow = height;
|
|
const unsigned int maxCol = width * RGBA_BYTES;
|
|
const int colorRed = 0;
|
|
const int colorGreen = 1;
|
|
const int colorBlue = 2;
|
|
const int colorAlpha = 3;
|
|
for (unsigned int row = 0; row < maxRow; row++) {
|
|
for (unsigned int col = 0; col < maxCol; col += RGBA_BYTES) {
|
|
rgba[pos++] = row_pointers[row][col + colorRed]; // colorRed
|
|
rgba[pos++] = row_pointers[row][col + colorGreen]; // colorGreen
|
|
rgba[pos++] = row_pointers[row][col + colorBlue]; // colorBlue
|
|
rgba[pos++] = row_pointers[row][col + colorAlpha]; // colorAlpha
|
|
}
|
|
}
|
|
// clean up after the read, and free any memory allocated
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
|
fclose(file);
|
|
// set bitmap info
|
|
bitmapInfo.bitmap = reinterpret_cast<void* >(rgba);
|
|
bitmapInfo.format = CAPTION_OSD_PF_8888;
|
|
bitmapInfo.srcRect = {0, 0, width, height};
|
|
return true;
|
|
}
|
|
// free bitmap
|
|
void BaseView::FreePNG(DolBitmapInfo &bitmapInfo)
|
|
{
|
|
if (bitmapInfo.bitmap != nullptr) {
|
|
free(bitmapInfo.bitmap);
|
|
bitmapInfo.bitmap = nullptr;
|
|
}
|
|
}
|
|
BaseView::BaseView(unsigned int tempW, unsigned int tempH, unsigned int tempScale)
|
|
{
|
|
w = static_cast<unsigned short>(tempW);
|
|
h = static_cast<unsigned short>(tempH);
|
|
scale = static_cast<unsigned short>(tempScale);
|
|
}
|
|
BaseView::~BaseView()
|
|
{
|
|
}
|
|
|
|
// mute view
|
|
MuteView::MuteView(unsigned int tempW, unsigned int tempH, unsigned int tempScale)
|
|
: BaseView(tempW, tempH, tempScale)
|
|
{
|
|
isAble = false;
|
|
isMute = false;
|
|
bitmapInfo.bitmap = nullptr;
|
|
bitmapInfo.dstRect = {0, 0, 0, 0};
|
|
bitmapInfo.srcRect = {0, 0, 0, 0};
|
|
bitmapInfo.format = CAPTION_OSD_PF_8888;
|
|
}
|
|
void MuteView::InitView()
|
|
{
|
|
const unsigned short width = 192; // 192 is 1/20 of 3840, which is 4k mode
|
|
const unsigned short height = 108; // 108 is 1/20 of 2160, which is 4k mode
|
|
if (DecodePNG(bitmapInfo, (VIEW_PNG_PATH + MUTE_PNG_NAME).c_str())) {
|
|
const unsigned int tmpW = bitmapInfo.srcRect.width > width ? width : bitmapInfo.srcRect.width;
|
|
const unsigned int tmpH = bitmapInfo.srcRect.height > height ? height : bitmapInfo.srcRect.height;
|
|
const unsigned int tmpS = scale < 2 ? scale : 2; // 2 is default 4k mode scale
|
|
const unsigned int bitmapW = tmpW * tmpS;
|
|
const unsigned int bitmapH = tmpH * tmpS;
|
|
bitmapInfo.dstRect.width = bitmapW;
|
|
bitmapInfo.dstRect.height = bitmapH;
|
|
bitmapInfo.dstRect.x = w - bitmapW - MUTE_PNG_MARGIN; // the extreme right corner of the screen
|
|
bitmapInfo.dstRect.y = h - bitmapH - MUTE_PNG_MARGIN; // at the bottom of the screen is the most
|
|
} else {
|
|
ALOGE("MuteView::InitView: decode bitmapInfo failure");
|
|
}
|
|
}
|
|
void MuteView::SetMuteInfo(const bool able, const bool mute)
|
|
{
|
|
isAble = able;
|
|
isMute = mute;
|
|
}
|
|
void MuteView::DrawView(unique_ptr<DolGLDrawSurface> &gles)
|
|
{
|
|
if (gles == nullptr) {
|
|
ALOGE("MuteView::DrawView: gles is NULL");
|
|
return;
|
|
}
|
|
if (bitmapInfo.bitmap == nullptr) {
|
|
ALOGE("MuteView::DrawView: bitmap is NULL");
|
|
return;
|
|
}
|
|
if (isAble && isMute) {
|
|
int ret = gles->DolDrawBitmapByBlend(FBO_HANDLE_INDEX, bitmapInfo);
|
|
if (ret != DOL_NO_ERROR) {
|
|
ALOGE("MuteView::DrawView: DolDisplayBitmap failure(%d)", ret);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
MuteView::~MuteView()
|
|
{
|
|
FreePNG(bitmapInfo);
|
|
}
|
|
|
|
// volume bar view
|
|
VolumeBarView::VolumeBarView(unsigned int tempW, unsigned int tempH, unsigned int tempScale)
|
|
: BaseView(tempW, tempH, tempScale)
|
|
{
|
|
isAble = false;
|
|
volumeValue = 0;
|
|
volumeBarW = 0;
|
|
volumeBarX = 0;
|
|
fgColor = {0x33, 0xcc, 0xff, 0xff};
|
|
volumeRect = {0, 0, 0, 0};
|
|
barRect = {0, 0, 0, 0};
|
|
barRoundL = {0, 0, 0, 0};
|
|
barRoundR = {0, 0, 0, 0};
|
|
bitmapBG.bitmap = nullptr;
|
|
bitmapBG.dstRect = {0, 0, 0, 0};
|
|
bitmapBG.srcRect = {0, 0, 0, 0};
|
|
bitmapBG.format = CAPTION_OSD_PF_8888;
|
|
volumeText.text = u" ";
|
|
volumeText.textLen = strlen(" ");
|
|
volumeText.isBold = true;
|
|
volumeText.isItalic = false;
|
|
volumeText.isUnderLine = false;
|
|
volumeText.justify = 0;
|
|
volumeText.fontSize = 0;
|
|
volumeText.bgColor = {0x00, 0x00, 0x00, 0x00};
|
|
volumeText.fgColor = fgColor;
|
|
int ret = memset_s(bufW, sizeof(bufW), 0, sizeof(bufW));
|
|
if (ret != EOK) {
|
|
ALOGE("VolumeBarView memset_s bufW is failure");
|
|
return;
|
|
}
|
|
}
|
|
void VolumeBarView::InitView()
|
|
{
|
|
unsigned int bgW = VOLUME_BG_WIDTH_MIX * w; // view width: Fixed screen width of 0.625
|
|
unsigned int bgH = VOLUME_BG_HEIGHT * scale; // view height: fixed 92 pixel if screen is 1920*1080
|
|
unsigned int bgX = (w - bgW) * CENTRE_PARAM; // view position: horizontal centre
|
|
unsigned int bgY = h - bgH - VOLUME_PNG_MARGIN; // view position: screen bottom
|
|
// init bitmap background
|
|
if (DecodePNG(bitmapBG, (VIEW_PNG_PATH + VOLUME_PNG_NAME).c_str())) {
|
|
bitmapBG.dstRect.x = bgX;
|
|
bitmapBG.dstRect.y = bgY;
|
|
bitmapBG.dstRect.width = bgW;
|
|
bitmapBG.dstRect.height = bgH;
|
|
} else {
|
|
ALOGE("VolumeBarView::InitView: decode bitmapBG failure");
|
|
}
|
|
// init volume bar location
|
|
const unsigned int barH = VOLUME_BAR_H_MIX * bgH - VOLUME_BAR_MARGIN;
|
|
const unsigned int barW = VOLUME_BAR_W_MIX * bgW;
|
|
const unsigned int barX = (w - barW) * CENTRE_PARAM - VOLUME_BAR_MARGIN; // horizontal centre
|
|
const unsigned int barY = bgY + barH + VOLUME_BAR_OFFSET;
|
|
const unsigned int barR = barH * CENTRE_PARAM; // round R is height / 2
|
|
barRoundL = {barX, barY + barR, barR, barR};
|
|
barRoundR = {0, barY + barR, barR, barR};
|
|
barRect = {barX, barY, 0, barH};
|
|
SetVolumeBarW(barW);
|
|
SetVolumeBarX(barX);
|
|
// init volume text info and location
|
|
const unsigned short maxSize = VOLUME_BAR_H_MIX * VOLUME_BG_HEIGHT;
|
|
const unsigned short textSize = barH > maxSize ? maxSize : barH;
|
|
// text bytes max is 3, for example 100
|
|
const unsigned int textW = static_cast<unsigned int>(textSize) * VOLUME_MAX_BYTES;
|
|
const unsigned int textH = textSize;
|
|
const unsigned int textX = bgX + bgW * VOLUME_TEXT_X_MIX;
|
|
const unsigned int textY = bgY + (bgH - textH) * CENTRE_PARAM; // vertical center
|
|
volumeText.fontSize = textSize; // text size is volume bar height
|
|
volumeRect = {textX, textY, textW, textH};
|
|
}
|
|
unsigned int VolumeBarView::GetVolumeBarW()
|
|
{
|
|
return volumeBarW;
|
|
}
|
|
unsigned int VolumeBarView::GetVolumeBarX()
|
|
{
|
|
return volumeBarX;
|
|
}
|
|
void VolumeBarView::SetVolumeBarW(unsigned int w)
|
|
{
|
|
volumeBarW = w;
|
|
}
|
|
void VolumeBarView::SetVolumeBarX(unsigned int x)
|
|
{
|
|
volumeBarX = x;
|
|
}
|
|
void VolumeBarView::SetVolumeInfo(const bool able, const int vol)
|
|
{
|
|
isAble = able;
|
|
volumeValue = vol;
|
|
// set volume value
|
|
for (size_t i = 0; i < sizeof(std::to_string(vol).c_str()); i++) {
|
|
bufW[i] = *(std::to_string(vol).c_str() + i); // utf-8 to utf-16
|
|
}
|
|
volumeText.text = (const char16_t*)bufW;
|
|
volumeText.textLen = sizeof(std::to_string(vol).c_str());
|
|
// set volume bar width
|
|
unsigned int validBarW = (volumeValue / VOLUME_MAX_VALUE) * GetVolumeBarW();
|
|
barRect.width = validBarW;
|
|
barRoundR.x = GetVolumeBarX() + validBarW;
|
|
}
|
|
void VolumeBarView::DrawView(unique_ptr<DolGLDrawSurface> &gles)
|
|
{
|
|
if (gles == nullptr) {
|
|
ALOGE("VolumeBarView::DrawView: gles is NULL");
|
|
return;
|
|
}
|
|
if (bitmapBG.bitmap == nullptr) {
|
|
ALOGE("VolumeBarView::DrawView: bitmap is NULL");
|
|
return;
|
|
}
|
|
if (isAble) {
|
|
int ret = gles->DolDrawBitmapByBlend(FBO_HANDLE_INDEX, bitmapBG);
|
|
if (ret != DOL_NO_ERROR) {
|
|
ALOGE("VolumeBarView::DrawView: DolDisplayBitmap failure(%d)", ret);
|
|
return;
|
|
}
|
|
ret = gles->DolDrawText(FBO_HANDLE_INDEX, volumeText, volumeRect);
|
|
if (ret != DOL_NO_ERROR) {
|
|
ALOGE("CountDownView::DrawView: DolDrawText failure(%d)", ret);
|
|
return;
|
|
}
|
|
if (volumeValue == 0) {
|
|
ALOGI("CountDownView::DrawView: cancel draw volume bar");
|
|
return;
|
|
}
|
|
ret = gles->DolDrawRect(FBO_HANDLE_INDEX, barRect, fgColor);
|
|
if (ret != DOL_NO_ERROR) {
|
|
ALOGE("CountDownView::DrawView: DolDrawRect failure(%d)", ret);
|
|
}
|
|
ret = gles->DolDrawRound(FBO_HANDLE_INDEX, barRoundL, fgColor);
|
|
if (ret != DOL_NO_ERROR) {
|
|
ALOGE("CountDownView::DrawView: DolDrawRound left failure(%d)", ret);
|
|
}
|
|
ret = gles->DolDrawRound(FBO_HANDLE_INDEX, barRoundR, fgColor);
|
|
if (ret != DOL_NO_ERROR) {
|
|
ALOGE("CountDownView::DrawView: DolDrawRound right failure(%d)", ret);
|
|
}
|
|
}
|
|
}
|
|
VolumeBarView::~VolumeBarView()
|
|
{
|
|
FreePNG(bitmapBG);
|
|
}
|
|
|
|
// count down view
|
|
CountDownView::CountDownView(unsigned int tempW, unsigned int tempH, unsigned int tempScale)
|
|
: BaseView(tempW, tempH, tempScale)
|
|
{
|
|
remainTime = 0; // remaining time
|
|
rectTime = {0, 0, 0, 0};
|
|
bitmapBG.bitmap = nullptr;
|
|
bitmapBG.dstRect = {0, 0, 0, 0};
|
|
bitmapBG.srcRect = {0, 0, 0, 0};
|
|
bitmapBG.format = CAPTION_OSD_PF_8888;
|
|
bitmapText.bitmap = nullptr;
|
|
bitmapText.dstRect = {0, 0, 0, 0};
|
|
bitmapText.srcRect = {0, 0, 0, 0};
|
|
bitmapText.format = CAPTION_OSD_PF_8888;
|
|
|
|
textTime.text = u" ";
|
|
textTime.textLen = strlen(" ");
|
|
textTime.isBold = true;
|
|
textTime.isItalic = false;
|
|
textTime.isUnderLine = false;
|
|
textTime.justify = 0;
|
|
textTime.fontSize = 0;
|
|
textTime.bgColor = {0x00, 0x00, 0x00, 0x00};
|
|
textTime.fgColor = {0xff, 0xc6, 0x00, 0xff};
|
|
int ret = memset_s(bufW, sizeof(bufW), 0, sizeof(bufW));
|
|
if (ret != EOK) {
|
|
ALOGE("CountDownView memset_s bufW is failure");
|
|
return;
|
|
}
|
|
}
|
|
void CountDownView::InitView()
|
|
{
|
|
const unsigned short tmpScale = scale < 2 ? scale : 2; // 2 is default scale
|
|
const unsigned int viewW = COUNTDOWN_VIEW_W * tmpScale;
|
|
const unsigned int viewH = COUNTDOWN_VIEW_H * tmpScale;
|
|
const unsigned int viewX = w - viewW;
|
|
const unsigned int viewY = 0;
|
|
unsigned int textW, textH, textX, textY; // textBitmap info
|
|
// init bitmap bg
|
|
if (DecodePNG(bitmapBG, (VIEW_PNG_PATH + COUNTDOWN_BG_NAME).c_str())) {
|
|
bitmapBG.dstRect.x = viewX;
|
|
bitmapBG.dstRect.y = viewY;
|
|
bitmapBG.dstRect.width = viewW;
|
|
bitmapBG.dstRect.height = viewH;
|
|
} else {
|
|
ALOGE("CountDownView::InitView: decode bitmapBG failure");
|
|
}
|
|
// init bitmap text
|
|
if (DecodePNG(bitmapText, GetTextPngPath().c_str())) {
|
|
// keep the src bitmap scale ratio: newW / newH = oldW / oldH
|
|
textW = viewW * COUNTDOWN_TEXT_X_MIX;
|
|
textH = textW * bitmapText.srcRect.height / bitmapText.srcRect.width;
|
|
textX = viewX;
|
|
textY = viewY + (viewH - textH) * CENTRE_PARAM; // vertical center
|
|
bitmapText.dstRect.x = textX;
|
|
bitmapText.dstRect.y = textY;
|
|
bitmapText.dstRect.width = textW;
|
|
bitmapText.dstRect.height = textH;
|
|
} else {
|
|
ALOGE("CountDownView::InitView: decode bitmapText failure");
|
|
textW = viewW * COUNTDOWN_TEXT_X_MIX;
|
|
textH = viewH * CENTRE_PARAM;
|
|
textX = viewX;
|
|
textY = viewY + (viewH - textH) * CENTRE_PARAM; // vertical center
|
|
}
|
|
// init text time
|
|
const unsigned int timeW = viewW - textW;
|
|
const unsigned int timeH = textH;
|
|
const unsigned int timeX = textX + textW + COUNTDOWN_TEXT_MARGIN;
|
|
const unsigned int timeY = textY; // vertical center
|
|
textTime.fontSize = timeH;
|
|
rectTime = {timeX, timeY, timeW, timeH};
|
|
}
|
|
string CountDownView::GetTextPngPath()
|
|
{
|
|
auto configer = make_unique<BootvideoConfiger>();
|
|
if (configer->IsCountDownCH()) {
|
|
return VIEW_PNG_PATH + COUNTDOWN_CH_NAME;
|
|
} else {
|
|
return VIEW_PNG_PATH + COUNTDOWN_EN_NAME;
|
|
}
|
|
}
|
|
void CountDownView::SetRemainTime(int remain)
|
|
{
|
|
remainTime = remain;
|
|
// clear buf
|
|
int ret = memset_s(bufN, sizeof(bufN), '\0', sizeof(bufN)); // reset buf
|
|
if (ret != EOK) {
|
|
ALOGE("memset_s time_buf failure");
|
|
return;
|
|
}
|
|
// measure time_buf size
|
|
int size = snprintf_s(bufN, sizeof(bufN), sizeof(bufN) - 1, "%d%s", remainTime, "s");
|
|
if (size == -1) {
|
|
ALOGE("snprintf_s time_buf failure");
|
|
return;
|
|
}
|
|
// utf-8 to utf-16
|
|
for (size_t i = 0; i < strlen(bufN); i++) {
|
|
bufW[i] = bufN[i];
|
|
}
|
|
textTime.text = (const char16_t *)bufW;
|
|
textTime.textLen = strlen(bufN);
|
|
}
|
|
void CountDownView::DrawView(unique_ptr<DolGLDrawSurface> &gles)
|
|
{
|
|
if (gles == nullptr) {
|
|
ALOGE("MuteView::DrawView: gles is NULL");
|
|
return;
|
|
}
|
|
// draw bg
|
|
if (bitmapBG.bitmap != nullptr) {
|
|
int ret = gles->DolDrawBitmapByBlend(FBO_HANDLE_INDEX, bitmapBG);
|
|
if (ret != DOL_NO_ERROR) {
|
|
ALOGE("CountDownView::DrawView: draw bitmapBG failure(%d)", ret);
|
|
}
|
|
}
|
|
// draw text png
|
|
if (bitmapText.bitmap != nullptr) {
|
|
int ret = gles->DolDrawBitmapByBlend(FBO_HANDLE_INDEX, bitmapText);
|
|
if (ret != DOL_NO_ERROR) {
|
|
ALOGE("CountDownView::DrawView: draw bitmapText failure(%d)", ret);
|
|
}
|
|
}
|
|
// draw text
|
|
int ret = gles->DolDrawText(FBO_HANDLE_INDEX, textTime, rectTime);
|
|
if (ret != DOL_NO_ERROR) {
|
|
ALOGE("CountDownView::DrawView: DolDrawText failure(%d)", ret);
|
|
}
|
|
}
|
|
CountDownView::~CountDownView()
|
|
{
|
|
FreePNG(bitmapBG);
|
|
FreePNG(bitmapText);
|
|
}
|
|
|
|
// ui exit state
|
|
void BootvideoUI::SetUIFinish()
|
|
{
|
|
pthread_mutex_lock(&g_mtxFinish);
|
|
isExitUI = true;
|
|
PostUiLock();
|
|
pthread_mutex_unlock(&g_mtxFinish);
|
|
}
|
|
bool BootvideoUI::CheckExit() const
|
|
{
|
|
bool tempState = false;
|
|
pthread_mutex_lock(&g_mtxFinish);
|
|
tempState = isExitUI;
|
|
pthread_mutex_unlock(&g_mtxFinish);
|
|
return tempState;
|
|
}
|
|
// ui ready state
|
|
void BootvideoUI::SetUIReady()
|
|
{
|
|
pthread_mutex_lock(&g_mtxReady);
|
|
isGlesReady = true;
|
|
pthread_mutex_unlock(&g_mtxReady);
|
|
}
|
|
bool BootvideoUI::CheckReady() const
|
|
{
|
|
bool tempState = false;
|
|
pthread_mutex_lock(&g_mtxReady);
|
|
tempState = isGlesReady;
|
|
pthread_mutex_unlock(&g_mtxReady);
|
|
return tempState;
|
|
}
|
|
void BootvideoUI::SetVolumeStatus(int needUI, int mute, int volume) const
|
|
{
|
|
pthread_mutex_lock(&g_mtxView);
|
|
const int eventVolume = 1; // volume ui event
|
|
const int eventMute = 2; // mute ui event
|
|
bool ableMute = ((needUI == eventMute) ? true : false);
|
|
bool ableVolume = ((needUI == eventVolume) ? true : false);
|
|
if (muteView != nullptr) {
|
|
muteView->SetMuteInfo(ableMute, ((mute != 0) ? true : false));
|
|
}
|
|
if (volumeView != nullptr) {
|
|
volumeView->SetVolumeInfo(ableVolume, volume);
|
|
}
|
|
PostUiLock();
|
|
pthread_mutex_unlock(&g_mtxView);
|
|
}
|
|
void BootvideoUI::SetCountdownTime(int time) const
|
|
{
|
|
pthread_mutex_lock(&g_mtxView);
|
|
if (countView != nullptr) {
|
|
countView->SetRemainTime(time);
|
|
}
|
|
PostUiLock();
|
|
pthread_mutex_unlock(&g_mtxView);
|
|
}
|
|
} // namespace android
|