其实与android开机动画启动流程基本一模一样。除了文件换了位置,就是添加了一些函数。
内核起来后会启动第一个进程,即init进程。
init进程会根据init.rc配置启动surfaceflinger进程。
service surfaceflinger /system/bin/surfaceflingerclass mainuser systemgroup graphics drmrpconrestart restart zygote
surfaceflinger进程便启动了,跟着就会跑进程的main()函数。
frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp
int main(int argc, char** argv) {....// instantiate surfaceflingersp<SurfaceFlinger> flinger = new SurfaceFlinger();//创建surfaceflinger服务实例....flinger->init();// publish surface flingersp<IServiceManager> sm(defaultServiceManager());sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);//注册到service manager里// run in this threadflinger->run();//开跑return 0;}
首先new一个SurfaceFlinger实例,然后init,然后run
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::init() {ALOGI( "SurfaceFlinger's main thread ready to run. ""Initializing graphics H/W...");.....// start boot animationstartBootAnim();//开始播放动画}
初始化graphics之后,就调用startBootAnim()播放开机动画。
void SurfaceFlinger::startBootAnim() {// start boot animationmBootFinished = 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进程,动画就开始播放了。
下面来到bootanimation的实现
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 objectsp<BootAnimation> boot = new BootAnimation();//创建BootAnimation实例IPCThreadState::self()->joinThreadPool();//binder线程池,与surfaceflinger通信用的。}return 0;}
new一个BootAnimation实例,然后建个binder线程池,因为BootAnimation在显示动画时要与SurfaceFlinger服务进程通信,所以要启个binder线程池。
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 surfacesp<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 eglconst 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 anymoreproperty_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 immediatelyif(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 exitif(exitPending() && !part.count)break;}// free the textures for this partif (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 shutdownchar 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
来到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重写了,如下
ActivityManagerService.java
@Overridepublic 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);}
调用activityIdleInternalLocked函数,在下面实现
ActivityStackSupervisor.java
final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,Configuration config) {...if (booting || enableScreen) {mService.postFinishBooting(booting, enableScreen);//调用postFinishBooting}....}
postFinishBooting的实现
ActivityManagerService.java
void postFinishBooting(boolean finishBooting, boolean enableScreen) {mHandler.sendMessage(mHandler.obtainMessage(FINISH_BOOTING_MSG,finishBooting? 1 : 0, enableScreen ? 1 : 0));}
发送了一个FINISH_BOOTING_MSG
case FINISH_BOOTING_MSG: {if (msg.arg1 != 0) {finishBooting();}if (msg.arg2 != 0) {enableScreenAfterBoot();}break;}
收到消息,调用enableScreenAfterboot()
ActivityManagerService.java
void enableScreenAfterBoot() {EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,SystemClock.uptimeMillis());mWindowManager.enableScreenAfterBoot();//调WindowManagerService类里的enableScreenAfterBoot()函数synchronized (this) {updateEventDispatchingLocked();}}
来到WindowManagerService.java
public void enableScreenAfterBoot() {....performEnableScreen();}
performEnableScreen()实现
public void performEnableScreen() {.....surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHEDdata, 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);};
frameworks/native/libs/gui/ISurfaceComposer.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 unreachablereturn 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()检测到就退出进程,停止播放。