概述
智能手機的開機畫面一般是由一幀靜態圖片或者一組靜態圖片組成。一組動態圖片可以在代碼中實現開機動畫的效果。爲了豐富開機界面的形式,百變開機畫面補充了這樣的需求。
可以實現開機播放自定義視頻,又可以兼容開機播放靜態圖片的功能。
該功能主要由兩個bin服務實現
Counter服務是屬於系統bin服務,位置在/system/bin/counter,擁有系統權限,可以讀寫系統file,實現開機畫面的倒計時功能與開機靜態圖片的展示。
Play服務是屬於系統bin服務,位置在/system/bin/counter,擁有系統權限,可以讀寫系統file,實現開機自定義視頻功能,可以支持mp4,ts等常見視頻格式
類Counte實現
counter.cpp是一個顯性的倒計時提示,在用戶自定義的開機視頻和開機畫面上顯示剩餘秒數提示用戶,同時如果有靜態圖片,背景顯示圖片。
1. Counter是系統bin服務,通過createSurface創建實例作爲圖層:
status_t Counter::readyToRun() {
//獲取內建顯示設備
sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
ISurfaceComposer::eDisplayIdMain));
DisplayInfo dinfo;
//獲取默認的Display對象參數
status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
if (status)
return -1;
// 創建native SurfaceView
sp<SurfaceControl> control = session()->createSurface(String8("Counter"),
dinfo.w, dinfo.h, PIXEL_FORMAT_RGBA_8888, 0);
//操作SurfaceComposeClient,並設置圖層優先級
SurfaceComposerClient::openGlobalTransaction();
control->setLayer(0x40000002);
SurfaceComposerClient::closeGlobalTransaction();
sp<Surface> s = control->getSurface();
// 初始化 opengl 和 egl引擎參數
const EGLint attribs[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 0,
EGL_NONE
};
2. 加載系統默認UI資源,通過decodeImage來解碼圖片,並顯示在SurfaceLayer之上。
status_t Counter::initTexture(Texture* texture, AssetManager& assets,
const char* name) {
//聲明bitmap對象
SkBitmap bitmap;
//通過sk庫函數對圖片進行decode
SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(),
&bitmap, kUnknown_SkColorType, SkImageDecoder::kDecodePixels_Mode);
//assert對象關閉,釋放資源
asset->close();
delete asset;
……
}
類Player.cpp 實現
Player.cpp是檢查data目錄下是否有視頻文件,通過在開機界面繪製surfaceview來播放視頻。
在surfacelinger服務初始化完成後,啓動Player服務,創建surface示例並設置初始化view參數。這部分與初始化Counter過程一樣,需要創建Native Surface。
檢測目錄下視頻文件後,開始調用MediaPlayer播放視頻,獲取視頻時長,格式,設置倒計時服務,直到播放結束後進入系統。
播放視頻相關代碼流程:
int main(int argc, char **argv) {
android::ProcessState::self()->startThreadPool();
//初始化SurfaceComposerClient
sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
//獲取內建顯示設備
sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(
ISurfaceComposer::eDisplayIdMain));
//創建Surface,初始化相關參數
sp<SurfaceControl> control =
composerClient->createSurface(
String8("A Surface"),
displayWidth,
displayHeight,
PIXEL_FORMAT_RGB_565,
0);
SurfaceComposerClient::closeGlobalTransaction();
//創建MediaPlayer實例
sp<IMediaPlayer> player =
service->create(client, AUDIO_SESSION_ALLOCATE);
//設置播放源目標
if (player != NULL && player->setDataSource(source) == NO_ERROR) {
//設置播放Video的SurfaceTexture,用於顯示播放視頻流
player->setVideoSurfaceTexture(surface->getIGraphicBufferProducer());
//開始播放文件
player->start();
client->waitForEOS();
//播放停止
player->stop();
} else {
fprintf(stderr, "failed to instantiate player.\n");
}
//關閉composerClient
composerClient->dispose();
}
播放自定義視頻流程
Counter與Player加載分析:
在init.rc中添加counter與advert服務,user權限聲明爲root,初次啓動設置爲disabled,需要主動調起。
service connter /system/bin/counter
class core
user root
group graphics audio
disabled
oneshot
service player /system/bin/player
class core
user root
group graphics audio
disabled
oneshot