Android6.0 開機動畫(二) AMS通知系統啟動&WMS通知SurfaceFlinger關閉開機動畫
在http://blog.csdn.net/kc58236582/article/details/52794846部落格中我們已經講了開機動畫的大致流程,這裡我們就Launcher啟動後,Launcher的執行緒閒的時候在ActivityThread呼叫AMS的activityIdle方法。
在分析訊息機制 空閒訊息處理器中http://blog.csdn.net/kc58236582/article/details/52919904,我們知道在訊息執行緒空閒時會呼叫IdleHandler的queueIdle方法,這裡我們來看ActivityThread中的IdleHandler,是在ActivityThread的handleResumeActivity函式中有下面一段程式碼,呼叫了MessageQueue的addIdleHandler函式。
...... if (!r.onlyLocalRequest) { r.nextIdle = mNewActivities; mNewActivities = r; if (localLOGV) Slog.v( TAG, "Scheduling idle handler for " + r); Looper.myQueue().addIdleHandler(new Idler()); } ......
在Idler的queueIdle函式中呼叫了AMS的activityIdle函式,我們來看下,獲取ActivityStack後呼叫了activityIdleInternalLocked函式。
@Override public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) { final long origId = Binder.clearCallingIdentity(); synchronized (this) { ActivityStack stack = ActivityRecord.getStackLocked(token);//得到ActivityStack 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); }
看如下函式,我們先根據token來得到其ActivityRecord,然後將ActivityRecord的idle置為true。如果是isFrontStack呼叫checkFinishBootingLocked函式。
final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
Configuration config) {
if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token);
ArrayList<ActivityRecord> stops = null;
ArrayList<ActivityRecord> finishes = null;
ArrayList<UserState> startingUsers = null;
int NS = 0;
int NF = 0;
boolean booting = false;
boolean activityRemoved = false;
ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r != null) {
if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternalLocked: Callers="
+ Debug.getCallers(4));
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
r.finishLaunchTickingLocked();
if (fromTimeout) {
reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
}
// This is a hack to semi-deal with a race condition
// in the client where it can be constructed with a
// newer configuration from when we asked it to launch.
// We'll update with whatever configuration it now says
// it used to launch.
if (config != null) {
r.configuration = config;
}
// We are now idle. If someone is waiting for a thumbnail from
// us, we can now deliver.
r.idle = true;//idle置為true
//Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
if (isFrontStack(r.task.stack) || fromTimeout) {
booting = checkFinishBootingLocked();
}
}
......
checkFinishBootingLocked函式,如果AMS正在啟動會呼叫其postFinishBooting函式
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;
}
AMS的postFinishBooting函式傳送FINISH_BOOTING_MSG訊息
void postFinishBooting(boolean finishBooting, boolean enableScreen) {
mHandler.sendMessage(mHandler.obtainMessage(FINISH_BOOTING_MSG,
finishBooting ? 1 : 0, enableScreen ? 1 : 0));
}
我們再來看訊息處理,當finishBooting為true,就呼叫finishBooting函式,這個函式中會發送一些廣播,以及將SystemService啟動到PHASE_BOOT_COMPLETED階段。
case FINISH_BOOTING_MSG: {
if (msg.arg1 != 0) {
finishBooting();
}
if (msg.arg2 != 0) {
enableScreenAfterBoot();
}
break;
}
當enableScreen為true會呼叫enableScreenAfterBoot函式,會在這個函式中呼叫WMS的enableScreenAfterBoot函式
void enableScreenAfterBoot() {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
SystemClock.uptimeMillis());
mWindowManager.enableScreenAfterBoot();
synchronized (this) {
updateEventDispatchingLocked();
}
}
在WMS的enableScreenAfterBoot方法又會呼叫performEnableScreen方法,這個方法會呼叫SurfaceFlinger的Binder
public void performEnableScreen() {
synchronized(mWindowMap) {
if (mDisplayEnabled) {
return;
}
if (!mSystemBooted && !mShowingBootMessages) {
return;
}
// Don't enable the screen until all existing windows have been drawn.
if (!mForceDisplayEnabled && checkWaitingForWindowsLocked()) {
return;
}
if (!mBootAnimationStopped) {
// Do this one time.
try {
IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
if (surfaceFlinger != null) {
//Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
Parcel data = Parcel.obtain();
data.writeInterfaceToken("android.ui.ISurfaceComposer");
surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
data, null, 0);
data.recycle();
}
} catch (RemoteException ex) {
Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
}
mBootAnimationStopped = true;
}
......
FIRST_CALL_TRANSACTION就是BOOT_FINISHED 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,
我們再來看ISurfaceComposer.cpp對BOOT_FINISHED的處理,會呼叫bootFinished函式。 case BOOT_FINISHED: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
bootFinished();
return NO_ERROR;
}
bootFinished會計算開機的時間,然後將service.bootanim.exit屬性設為1,這樣bootanim會結束,這樣開機動畫結束。void SurfaceFlinger::bootFinished()
{
const nsecs_t now = systemTime();
const nsecs_t duration = now - mBootTime;
ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
mBootFinished = true;
// wait patiently for the window manager death
const String16 name("window");
sp<IBinder> window(defaultServiceManager()->getService(name));
if (window != 0) {
window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
}
// stop boot animation
// formerly we would just kill the process, but we now ask it to exit so it
// can choose where to stop the animation.
property_set("service.bootanim.exit", "1");
char boot_exit_value[32];
property_get("service.bootanim.exit", boot_exit_value, "0");
ALOGD("The service.bootanim.exit property value is %d", atoi(boot_exit_value));
}