開機動畫是在SurfaceFlinger實例通過調用startBootAnim()啟動的,BootAnim是如何啟動和結束的,總體框架圖如下:

1.init.rc
service surfaceflinger /system/bin/surfaceflinger class main user system group graphics drmrpc onrestart restart zygote
init進程會根據init.rc配置啟動surfaceflinger進程,surfaceflinger進程啟動了,跟着就會跑進程的main()函數。
2.frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp
int main(int argc, char** argv) { .... // instantiate surfaceflinger sp<SurfaceFlinger> flinger = new SurfaceFlinger();//創建surfaceflinger服務實例 .... flinger->init(); // publish surface flinger sp<IServiceManager> sm(defaultServiceManager()); sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);//注冊到service manager里 // run in this thread flinger->run();//運行 return 0; }
首先new一個SurfaceFlinger實例,然后init,然后run
3.frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::init() { ALOGI( "SurfaceFlinger's main thread ready to run. " "Initializing graphics H/W..."); ..... // start boot animation startBootAnim();//開始播放動畫 }
初始化graphics之后,就調用startBootAnim()播放開機動畫。
void SurfaceFlinger::startBootAnim() {
// start boot animation
mBootFinished = false;
property_set("service.bootanim.exit", "0");//這個會有bootanimation進程周期檢測,=1退出動畫
property_set("ctl.start", "bootanim");//通過ctl.start命令啟動bootanim
}
把service.bootanim.exit屬性設為0,這個屬性bootanimation進程里會周期檢查,=1時就退出動畫,這里=0表示要播放動畫。
后面通過ctl.start的命令啟動bootanim進程,動畫就開始播放了。
4.frameworks/base/cmds/bootanimation/bootanimation_main.cpp
int main(int argc, char** argv)
{
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
// create the boot animation object
sp<BootAnimation> boot = new BootAnimation();//創建BootAnimation實例
IPCThreadState::self()->joinThreadPool();//binder線程池,與surfaceflinger通信用的。
}
return 0;
}
new一個BootAnimation實例,然后建個binder線程池,因為BootAnimation在顯示動畫時要與SurfaceFlinger服務進程通信,所以要啟個binder線程池。
5.frameworks/base/cmds/bootanimation/BootAnimation.cpp
BootAnimation::BootAnimation() : Thread(false) { mSession = new SurfaceComposerClient();//創建一個對象 }
創建實例時,構造函數就會被調用,new一個SurfaceComposerClient實例,他是用來與surfaceflinger通信的
void BootAnimation::onFirstRef() {
status_t err = mSession->linkToComposerDeath(this);//注冊surfaceflinger死亡消息的通知書
ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
if (err == NO_ERROR) {
run("BootAnimation", PRIORITY_DISPLAY);//開跑
}
}
linkTocomposerDeath的作用是當surfaceflinger死掉是,BootAnimation就會得到通知。
如下,收到通知后就退出動畫了,因為surfaceflinger都掛掉了,播放不了了。
void BootAnimation::binderDied(const wp<IBinder>& who)
{
// woah, surfaceflinger died!
ALOGD("SurfaceFlinger died, exiting...");
// calling requestExit() is not enough here because the Surface code
// might be blocked on a condition variable that will never be updated.
kill( getpid(), SIGKILL );//收到surfaceflinger死亡的消息,好吧自己也跟着去了。
requestExit();
}
另一個函數run()在BootAnimation的父類Thead里,用來創建一個線程並跑起來。
父類
system/core/libutils/Threads.cpp
status_t Thread::run(const char* name, int32_t priority, size_t stack)
{
...
if (mCanCallJava) {
res = createThreadEtc(_threadLoop,//創建線程
this, name, priority, stack, &mThread);
} else {
res = androidCreateRawThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
}
....
}
創建_threadLoop線程
int Thread::_threadLoop(void* user)
{
....
do {
bool result;
if (first) {
first = false;
self->mStatus = self->readyToRun();//這個函數被bootanimation重寫了
result = (self->mStatus == NO_ERROR);
if (result && !self->exitPending()) {
...
result = self->threadLoop();//這個函數被bootanimation重寫了
}
} else {
result = self->threadLoop();
}
...
return 0;
}
readyToRun函數實現
status_t BootAnimation::readyToRun() {
mAssets.addDefaultAssets();
sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
ISurfaceComposer::eDisplayIdMain));
DisplayInfo dinfo;
status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
if (status)
return -1;
char value[PROPERTY_VALUE_MAX];
property_get("persist.panel.orientation", value, "0");
int orient = atoi(value) / 90;
if(orient == eOrientation90 || orient == eOrientation270) {
int temp = dinfo.h;
dinfo.h = dinfo.w;
dinfo.w = temp;
}
Rect destRect(dinfo.w, dinfo.h);
mSession->setDisplayProjection(dtoken, orient, destRect, destRect);
// create the native surface
sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
SurfaceComposerClient::openGlobalTransaction();
control->setLayer(0x40000000);
SurfaceComposerClient::closeGlobalTransaction();
sp<Surface> s = control->getSurface();
// initialize opengl and egl
const EGLint attribs[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_DEPTH_SIZE, 0,
EGL_NONE
};
EGLint w, h, dummy;
EGLint numConfigs;
EGLConfig config;
EGLSurface surface;
EGLContext context;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, 0, 0);
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
surface = eglCreateWindowSurface(display, config, s.get(), NULL);
context = eglCreateContext(display, config, NULL, NULL);
eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
return NO_INIT;
mDisplay = display;
mContext = context;
mSurface = surface;
mWidth = w;
mHeight = h;
mFlingerSurfaceControl = control;
mFlingerSurface = s;
mAndroidAnimation = true;
// If the device has encryption turned on or is in process
// of being encrypted we show the encrypted boot animation.
char decrypt[PROPERTY_VALUE_MAX];
property_get("vold.decrypt", decrypt, "");
bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);
if ((encryptedAnimation &&
(access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) &&
(mZip.open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE) == NO_ERROR)) ||
((access(USER_BOOTANIMATION_FILE, R_OK) == 0) &&
(mZip.open(USER_BOOTANIMATION_FILE) == NO_ERROR)) ||
((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) &&
(mZip.open(SYSTEM_BOOTANIMATION_FILE) == NO_ERROR))) {
mAndroidAnimation = false;
}
return NO_ERROR;
}
threadloop實現
bool BootAnimation::threadLoop()
{
bool r;
if (mAndroidAnimation) {
r = android();//顯示android默認動畫
} else {
r = movie();//顯示自定義的動畫
}
// No need to force exit anymore
property_set(EXIT_PROP_NAME, "0");
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(mDisplay, mContext);
eglDestroySurface(mDisplay, mSurface);
mFlingerSurface.clear();
mFlingerSurfaceControl.clear();
eglTerminate(mDisplay);
IPCThreadState::self()->stopProcess();
return r;
}
movie()的實現
bool BootAnimation::movie()
{
//讀取bootanimation.zip文件並解釋
// clear screen
//下面是循環顯示
for (int i=0 ; i<pcount ; i++) {
const Animation::Part& part(animation.parts[i]);
const size_t fcount = part.frames.size();
glBindTexture(GL_TEXTURE_2D, 0);
for (int r=0 ; !part.count || r<part.count ; r++) {
// Exit any non playuntil complete parts immediately
if(exitPending() && !part.playUntilComplete)
break;
for (int j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) {
const Animation::Frame& frame(part.frames[j]);
nsecs_t lastFrame = systemTime();
if (r > 0) {
glBindTexture(GL_TEXTURE_2D, frame.tid);
} else {
if (part.count != 1) {
glGenTextures(1, &frame.tid);
glBindTexture(GL_TEXTURE_2D, frame.tid);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
initTexture(
frame.map->getDataPtr(),
frame.map->getDataLength());
}
if (!clearReg.isEmpty()) {
Region::const_iterator head(clearReg.begin());
Region::const_iterator tail(clearReg.end());
glEnable(GL_SCISSOR_TEST);
while (head != tail) {
const Rect& r(*head++);
glScissor(r.left, mHeight - r.bottom,
r.width(), r.height());
glClear(GL_COLOR_BUFFER_BIT);
}
glDisable(GL_SCISSOR_TEST);
}
glDrawTexiOES(xc, yc, 0, animation.width, animation.height);
eglSwapBuffers(mDisplay, mSurface);
nsecs_t now = systemTime();
nsecs_t delay = frameDuration - (now - lastFrame);
//ALOGD("%lld, %lld", ns2ms(now - lastFrame), ns2ms(delay));
lastFrame = now;
if (delay > 0) {
struct timespec spec;
spec.tv_sec = (now + delay) / 1000000000;
spec.tv_nsec = (now + delay) % 1000000000;
int err;
do {
err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
} while (err<0 && errno == EINTR);
}
checkExit();//檢測是否退出動畫
}
usleep(part.pause * ns2us(frameDuration));
// For infinite parts, we've now played them at least once, so perhaps exit
if(exitPending() && !part.count)
break;
}
// free the textures for this part
if (part.count != 1) {
for (int j=0 ; j<fcount ; j++) {
const Animation::Frame& frame(part.frames[j]);
glDeleteTextures(1, &frame.tid);
}
}
}
return false;
}
那么到movie為止,動畫是在播放了,而且還在循環檢測是否退出,即checkExit()
checkExit()的實現
void BootAnimation::checkExit() {
// Allow surface flinger to gracefully request shutdown
char value[PROPERTY_VALUE_MAX];
property_get(EXIT_PROP_NAME, value, "0");//屬性為1,說明要退出了
int exitnow = atoi(value);
if (exitnow) {
requestExit();
}
}
property_get(EXIT_PROP_NAME, value, "0");檢測這個屬性,=1就退出動畫
#define EXIT_PROP_NAME "service.bootanim.exit"這個屬性就是上面講到的,等到launcher跑起來后就會置1
當launcher應用程序主線程跑起來后,如果主線程處於空閑,就會向ActivityManagerService發送一個activityIdle的消息。
應用程序主線程是ActivityThread.java來描述的,activityIdle是這個類來實現的
private class Idler implements MessageQueue.IdleHandler {
...
IActivityManager am = ActivityManagerNative.getDefault();
...
try {
am.activityIdle(a.token, a.createdConfig, stopProfiling);
a.createdConfig = null;
} catch (RemoteException ex) {
// Ignore
}
....
}
上面的ActivityManagerNavtive.getDefault()得到am
來到frameworks/base/core/java/android/app/ActivityManagerNative.java
static public IActivityManager getDefault() {
return gDefault.get();//getDefault的實現
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
gDefault實際上是IActivityManager,往下看
class ActivityManagerProxy implements IActivityManager
{
ActivityManagerProxy實現了IActivityManager
那么am.activityIdle()就是ActivityManagerProxy里的函數,如下
public void activityIdle(IBinder token, Configuration config, boolean stopProfiling)
throws RemoteException
{
...
mRemote.transact(ACTIVITY_IDLE_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);//發送ACTIVITY_IDLE_TRANSACTION
....
}
發送了ACTIVITY_IDLE_TRANSACTION的進程間通信,這個消息被ActivityManagerNative接收處理了。
case ACTIVITY_IDLE_TRANSACTION: {//收到消息
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
Configuration config = null;
if (data.readInt() != 0) {
config = Configuration.CREATOR.createFromParcel(data);
}
boolean stopProfiling = data.readInt() != 0;
if (token != null) {
activityIdle(token, config, stopProfiling);//這個函數在ActivityManagerService被重寫
}
reply.writeNoException();
return true;
}
收到消息后就調用了activityIdle函數,這個函數被ActivityManagerService重寫了,如下
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
@Override
public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
final long origId = Binder.clearCallingIdentity();
synchronized (this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
ActivityRecord r =
mStackSupervisor.activityIdleInternalLocked(token, false, config);
if (stopProfiling) {
if ((mProfileProc == r.app) && (mProfileFd != null)) {
try {
mProfileFd.close();
} catch (IOException e) {
}
clearProfilerLocked();
}
}
}
}
Binder.restoreCallingIdentity(origId);
}
frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java
final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
Configuration config) {
....
if (enableScreen) {
mService.enableScreenAfterBoot();//調ActivityManagerService類的enableScreenAfterBoot()函數
}
....
if (activityRemoved) {
resumeTopActivitiesLocked();
}
return r;
}
來到frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
void enableScreenAfterBoot() {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
SystemClock.uptimeMillis());
mWindowManager.enableScreenAfterBoot();//調WindowManagerService類里的enableScreenAfterBoot()函數
synchronized (this) {
updateEventDispatchingLocked();
}
}
來到frameworks/base/services/java/com/android/server/wm/WindowManagerService.java
public void enableScreenAfterBoot() { .... performEnableScreen(); }
performEnableScreen()實現
public void performEnableScreen() { ..... surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED data, null, 0); .... }
發送了FIRST_CALL_TRANSACTION的請求
因為從下面知道FIRST_CALL_TRANSACTION = BOOT_FINISHED
所以BnSurfaceComposer收到消息
frameworks/native/include/gui/ISurfaceComposer.h
class BnSurfaceComposer: public BnInterface<ISurfaceComposer> {
public:
enum {
// Note: BOOT_FINISHED must remain this value, it is called from
// Java by ActivityManagerService.
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
...
};
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags = 0);
};
</pre></p><p><span style="color:#333333;">frameworks/native/libs/gui/ISurfaceComposer.cpp</span></p><p><span style="color:#333333;"></span><pre name="code" class="cpp">status_t BnSurfaceComposer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
....
case BOOT_FINISHED: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
bootFinished();//調用 bootFinished()
return NO_ERROR;
}
....
}
// should be unreachable
return NO_ERROR;
}
bootFinished()函數BpSurfaceComposer里實現,但發現沒有,他又發了一個BOOT_FINISHED,死循環了,其實沒有。bootFinished()被SurfaceFlinger類重寫了
class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
{
virtual void bootFinished()
{
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
}
重寫
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::bootFinished() { ... property_set("service.bootanim.exit", "1"); }
把service.bootanim.exit寫成1,然后bootanimation進程的checkExit()檢測到就退出進程,停止播放。

