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

/*
* 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