Android启动之BOOT_COMPLETED广播

AMS启动Home(启动Launcher)

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public void systemReady(final Runnable goingCallback) {
    ... ...
    Slog.i(TAG, "System now ready");
    ... ...
    startHomeActivityLocked(mCurrentUserId, "systemReady"); //启动 Home
}



boolean startHomeActivityLocked(int userId, String reason) {
    if (mStartHomeSetDefaultLauncherCount > 0) {
            mStartHomeSetDefaultLauncherCount--;
            boolean firstLaunch = 
            SystemProperties.getBoolean("persist.sys.sw.firstLaunch", true);
            if(firstLaunch){
                setDefaultLauncher(); //设置默认launcher
                if (mStartHomeSetDefaultLauncherCount == 0) {
                    SystemProperties.set("persist.sys.sw.firstLaunch", "false");
                }
            }
        }
    ... ...
    Intent intent = getHomeIntent(); //获取Home的Intent
    ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId); 
    //如果系统没有任何Home应用,aInfo == null,不会启动Home
    //但是,如果系统是第一次启动或恢复出厂设置,会首先启动开机向导,此时aInfo != null
    if (aInfo != null) {
            intent.setComponent(new ComponentName( aInfo.applicationInfo.packageName, aInfo.name));
            // Don't do this if the home app is currently being
            // instrumented.
            aInfo = new ActivityInfo(aInfo);
            aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
            ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                    aInfo.applicationInfo.uid, true);
            if (app == null || app.instrumentationClass == null) {
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                Slog.w("zhangc","startHomeActivity intent "+intent+"; aInfo "+aInfo+"; reason "+reason);
                mStackSupervisor.startHomeActivity(intent, aInfo, reason); //此处启动Home应用
            }
    }
}

Home应用启动后,回调AMS的activityIdle方法

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
    ... ...
    ActivityRecord r = mStackSupervisor.activityIdleInternalLocked(token, false, config);
}
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout, Configuration config) {
    ... ...
    if (isFrontStack(r.task.stack) || fromTimeout) {
        booting = checkFinishBootingLocked();
    }
}

checkFinishBootingLocked会报告启动时间结束,以及检查是否是还在开机阶段,结束开机流程。当桌面已经拿到焦点显示好了,开机动画可以退出。在这里会修改AMS的mBooting全局变量为true,enableScreen也是true,发送Message给AMS进行处理。代码片段如下:

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

private boolean checkFinishBootingLocked() {
        final boolean booting = mService.mBooting;
        boolean enableScreen = false;
        mService.mBooting = false;
        if (!mService.mBooted) {
            mService.mBooted = true;
            enableScreen = true;
        }
        if (booting || enableScreen) {
            mService.postFinishBooting(booting, enableScreen);
        }
        return booting;
    }

postFinishBooting函数发送FINISH_BOOTING_MSG消息:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

void postFinishBooting(boolean finishBooting, boolean enableScreen) {
        mHandler.sendMessage(mHandler.obtainMessage(FINISH_BOOTING_MSG,
                finishBooting? 1 : 0, enableScreen ? 1 : 0));
}

处理FINISH_BOOTING_MSG消息:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

final class MainHandler extends Handler {
        public MainHandler(Looper looper) {
            super(looper, null, true);
        }
        @Override
        public void handleMessage(Message msg) {
            ... ...
            case FINISH_BOOTING_MSG: {
                if (msg.arg1 != 0) {
                    finishBooting();
                }
                if (msg.arg2 != 0) {
                    enableScreenAfterBoot();
                }
                break;
            }
        }
}

下面分别分析finishBootingenableScreenAfterBoot

finishBooting里面先判断开机动画有没有结束,如果没有结束,直接返回。如果已经结束,则经过一些处理,最后发送开机广播BOOT_COMPLETED。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

final void finishBooting() {
        synchronized (this) {
            if (!mBootAnimationComplete) {    //如果开机动画没有退出,直接返回
                mCallFinishBooting = true;
                return;
            }
            mCallFinishBooting = false;
        }

    // Tell anyone interested that we are done booting!
    SystemProperties.set("sys.boot_completed", "1");    //设置属性,表明开机完成
    ... ...
    Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
    intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
    intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
    broadcastIntentLocked... ...     //发送开机广播
}

那么,开机动画什么时候退出呢?继续往下看。

等待WMS准备好,SystemProperties.set("service.bootanim.exit", "1");,然后bootanimation退出。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
void enableScreenAfterBoot() {
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
                SystemClock.uptimeMillis());
        mWindowManager.enableScreenAfterBoot(); //退出bootanimation
        synchronized (this) {
            updateEventDispatchingLocked();
        }
}

经过一系列调用,最后设置service.bootanim.exit这个属性。

property_set("service.bootanim.exit", "1");

frameworks/ base/services/core/java/com/android/server/wm/WindowManagerService.java
enableScreenAfterBoot()  -> 
    performEnableScreen()  ->       
        surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION,  data, null, 0); ->

frameworks/native/ services/surfaceflinger/SurfaceFlinger.cpp
bootFinished() ->
    property_set("service.bootanim.exit", "1");  //将该属性设为1,开机动画退出。
发布了6 篇原创文章 · 获赞 2 · 访问量 356

猜你喜欢

转载自blog.csdn.net/zc37093/article/details/103244500