首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > Android >

Android 开机卡通源码分析

2013-10-08 
Android 开机动画源码分析Android系统在启动SystemServer进程时,通过两个阶段来启动系统所有服务,在第一阶

Android 开机动画源码分析

Android系统在启动SystemServer进程时,通过两个阶段来启动系统所有服务,在第一阶段启动本地服务,如SurfaceFlinger,SensorService等,在第二阶段则启动一系列的Java服务。开机动画是在什么时候启动的呢?通过查看源码,Android开机动画是在启动SurfaceFlinger服务时启动的。SystemServer的main函数首先调用init1来启动本地服务,init1函数通过JNI调用C语言中的system_init()函数来实现服务启动。


property_set("ctl.start", "bootanim")就是启动bootanim进程来显示开机动画,该进程对应的源码位于frameworks\base\cmds\bootanimation\bootanimation_main.cpp


Android 开机卡通源码分析

bool BootAnimation::movie(){    ZipFileRO& zip(mZip);//获取zip压缩文件中的文件数目    size_t numEntries = zip.getNumEntries();//打开zip压缩文件中的desc.txt文件    ZipEntryRO desc = zip.findEntryByName("desc.txt");    FileMap* descMap = zip.createEntryFileMap(desc);    ALOGE_IF(!descMap, "descMap is null");    if (!descMap) {        return false;    }//读取desc.txt文件内容    String8 desString((char const*)descMap->getDataPtr(),descMap->getDataLength());    char const* s = desString.string();    Animation animation;//读取persist.sys.silence属性来决定是否播放开机音乐    char silence[PROPERTY_VALUE_MAX];    property_get("persist.sys.silence", silence, "0");    if(strcmp("1", silence)==0){        // do something.    }else{        soundplay();    }//解析desc.txt文件内容    for (;;) {   //从字符串s中查找是否有字符串"\n",如果有,返回s中"\n"起始位置的指针,如果没有,返回null。        const char* endl = strstr(s, "\n");        if (!endl) break;//取得文件一行内容        String8 line(s, endl - s);        const char* l = line.string();        int fps, width, height, count, pause;        char path[256];        char pathType;//从文件第一行中读取宽度,高度,帧数//480 854 10 <---> width height fps        if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) {            //LOGD("> w=%d, h=%d, fps=%d", fps, width, height);            animation.width = (width > 0 ? width : mWidth);            animation.height = (height > 0 ? height : mHeight);            animation.fps = fps;//p 1 2 folder1 <---> pathType count pause path        }else if (sscanf(l, " %c %d %d %s", &pathType, &count, &pause, path) == 4) {            //LOGD("> type=%c, count=%d, pause=%d, path=%s", pathType, count, pause, path);            Animation::Part part;//一个part描述一个动画文件夹内容            part.playUntilComplete = pathType == 'c';            part.count = count;            part.pause = pause;            part.path = path;            animation.parts.add(part);        }        s = ++endl;    }    //读取动画个数    const size_t pcount = animation.parts.size();//遍历zip压缩包中的所有文件    for (size_t i=0 ; i<numEntries ; i++) {        char name[256];        ZipEntryRO entry = zip.findEntryByIndex(i);//读取压缩包中的文件名称,所在目录的路径        if (zip.getEntryFileName(entry, name, 256) == 0) {            const String8 entryName(name);            const String8 path(entryName.getPathDir());            const String8 leaf(entryName.getPathLeaf());            if (leaf.size() > 0) {                for (int j=0 ; j<pcount ; j++) {                    if (path == animation.parts[j].path) {                        int method;                        //获取文件信息                        if (zip.getEntryInfo(entry, &method, 0, 0, 0, 0, 0)) {                            if (method == ZipFileRO::kCompressStored) {                                FileMap* map = zip.createEntryFileMap(entry);                                if (map) {                                    Animation::Frame frame;                                    frame.name = leaf;                                    frame.map = map;                                    Animation::Part& part(animation.parts.editItemAt(j));                                    part.frames.add(frame);                                }                            }                        }                    }                }            }        }    }    // clear screen    glShadeModel(GL_FLAT);    glDisable(GL_DITHER);    glDisable(GL_SCISSOR_TEST);    glDisable(GL_BLEND);    glClearColor(0,0,0,1);    glClear(GL_COLOR_BUFFER_BIT);    eglSwapBuffers(mDisplay, mSurface);    glBindTexture(GL_TEXTURE_2D, 0);    glEnable(GL_TEXTURE_2D);    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);    const int xc = (mWidth - animation.width) / 2;    const int yc = ((mHeight - animation.height) / 2);    nsecs_t lastFrame = systemTime();    nsecs_t frameDuration = s2ns(1) / animation.fps;    Region clearReg(Rect(mWidth, mHeight));    clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height));    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);            }        }    }    soundstop();    return false;}


热点排行