1.1 Window窗口管理框架圖
WMS窗口管理
窗口的添加從Activity::makeVisible
開始秕硝,由WindowManagerImpl
委托給WindowManagerGlobal
處理机杜,WindowManagerGlobal
內(nèi)部的mViews
闰非、mRoots
碉咆、mParams
骏庸、mDyingViews
分別管理窗口的試圖、主線程景东、布局參數(shù)以及死亡過程中的視圖吞琐;ViewRootImpl
持有Session
的代理端與WMS通信捆探;
2.1 ActivityThread::handleLaunchActivity
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
...
// Initialize before creating the activity
WindowManagerGlobal.initialize(); // WindowManagerGlobal 初始化
Activity a = performLaunchActivity(r, customIntent); // 2.2 ActivityThread::performLaunchActivity
handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason); // 2.6 ActivityThread::handleResumeActivity
}
2.2 ActivityThread::performLaunchActivity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
Activity activity = null;
...
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent); //newInstance
...
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window); // 2.3 Activity::attach
...
mInstrumentation.callActivityOnCreate(activity, r.state); //OnCreate
...
activity.performStart();//Onstart
...
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); // OnRestoreInstanceState
}
2.3 Activity::attach
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window) {
attachBaseContext(context); //
mWindow = new PhoneWindow(this, window); // 新建PhoneWindow
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this); // Window.CallBack的實現(xiàn)類為Activity
mWindow.setOnWindowDismissedCallback(this);
...
mToken = token; // 添加一個Activity窗口所需要的令牌
...
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE), /* 2.4.1 獲取WindowManagerImpl */
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0); // 2.5.1 PhoneWindow::setWindowManager
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager(); // mWindowManager is WindowManagerImpl
mCurrentConfig = config;
}
2.4.1 ContextImpl::getSystemService
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name); // 2.4.2 SystemServiceRegistry::registerService
}
2.4.2 SystemServiceRegistry::registerService
registerService(Context.WINDOW_SERVICE, WindowManager.class,
new CachedServiceFetcher<WindowManager>() {
@Override
public WindowManager createService(ContextImpl ctx) {
return new WindowManagerImpl(ctx);
}});
2.5.1 PhoneWindow::setWindowManager
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) { // wm is WindowManagerImpl
mAppToken = appToken;
mAppName = appName;
mHardwareAccelerated = hardwareAccelerated
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
2.5.2 WindowManagerImpl::createLocalWindowManager
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
return new WindowManagerImpl(mContext, parentWindow);
}
2.6 ActivityThread::handleResumeActivity
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
...
r = performResumeActivity(token, clearHide, reason);
// r.activity.performResume() -> Activity::OnResume
...
if (r != null) {
final Activity a = r.activity;
...
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow(); // PhoneWindow
View decor = r.window.getDecorView(); // 2.6.1 PhoneWindow::getDecorView
decor.setVisibility(View.INVISIBLE); // Activity的窗口在初創(chuàng)時不可見,因為尚不確定是否真的要顯示窗口給用戶
ViewManager wm = a.getWindowManager(); // WindowManagerImpl
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; // 類型:屬于Acitivity的窗口
l.softInputMode |= forwardBit;
if (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
// Normally the ViewRoot sets up callbacks with the Activity
// in addView->ViewRootImpl#setView. If we are instead reusing
// the decor view we have to notify the view root that the
// callbacks may have changed.
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if (a.mVisibleFromClient && !a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l); // WM is windowManagerImpl站粟,添加到WMS
}
}
// The window is now visible if it has been added, we are not
// simply finishing, and we are not starting another activity.
if (!r.activity.mFinished && willBeVisible
&& r.activity.mDecor != null && !r.hideForNow) {
...
WindowManager.LayoutParams l = r.window.getAttributes();
...
if (r.activity.mVisibleFromClient) {
ViewManager wm = a.getWindowManager();
View decor = r.window.getDecorView();
wm.updateViewLayout(decor, l); // 通知wms更新布局
}
...
r.activity.makeVisible(); // 2.7 設置可見
...
}
...
if (!r.onlyLocalRequest) {
r.nextIdle = mNewActivities;
mNewActivities = r;
Looper.myQueue().addIdleHandler(new Idler()); //
}
ActivityManagerNative.getDefault().activityResumed(token); // 通知AMS Activity處于Resumed狀態(tài)
} else {
// If an exception was thrown when trying to resume, then
// just end this activity.
// resume過程發(fā)生異常黍图,則 finishActivity
ActivityManagerNative.getDefault()
.finishActivity(token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
}
}
2.6.1 PhoneWindow::getDecorView
public final View getDecorView() {
if (mDecor == null || mForceDecorInstall) {
installDecor(); // 2.6.2
}
return mDecor;
}
2.6.2 PhoneWindow::installDecor
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
mDecor = generateDecor(-1); // 2.6.3
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
} else {
mDecor.setWindow(this); // PhoneWindow::mWindow is PhoneWindow
}
}
2.6.3 PhoneWindow::generateDecor
protected DecorView generateDecor(int featureId) {
// System process doesn't have application context and in that case we need to directly use
// the context we have. Otherwise we want the application context, so we don't cling to the
// activity.
Context context;
...
context = getContext();
...
return new DecorView(context, featureId, this, getAttributes());
}
2.6.4 ActivityDecorView相關結(jié)構(gòu)圖
ActivityDecorView相關結(jié)構(gòu)圖
Activity
中DecorView
為根視圖
2.7 Activity::makeVisible 設置窗口可見
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes()); // 2.9 委托WindowManagerGlobal添加到wms
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE); // 設置DecorView可見
}
2.8 WindowManagerImpl相關框架圖
WindowManagerImpl相關架構(gòu)圖
接口ViewManager
定義了view
的基本操作增(addView
)、刪(removeView
)奴烙、更新(updateViewLayout
);
接口WindowManger
繼承自ViewManager
助被;
WindowManagerImpl
實現(xiàn)WindowManager
中的方法,并委托給WindowMangerGlobal
處理缸沃;
WindowManagerGlobal
中的mViews
恰起、mRoots
修械、mParams
趾牧、mDyingViews
分別管理窗口的試圖、主線程肯污、布局參數(shù)以及死亡的試圖翘单;
2.9 WindowManagerGlobal::addView
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
// 參數(shù)檢查
...
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
...
int index = findViewLocked(view, false);
if (index >= 0) {
if (mDyingViews.contains(view)) {
// Don't wait for MSG_DIE to make it's way through root's queue.
mRoots.get(index).doDie(); // 3.1 如果已經(jīng)包含此view,則先remove
}
}
...
root = new ViewRootImpl(view.getContext(), display); // 2.12 ViewRootImpl構(gòu)造過程獲取WindowSession
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams); // 保存當前window
}
try {
root.setView(view, wparams, panelParentView); // 2.12 更新布局
} catch (RuntimeException e) {
synchronized (mLock) {
final int index = findViewLocked(view, false);
if (index >= 0) {
removeViewLocked(index, true); // remove試圖
}
}
}
}
2.10 WindowManagerGlobal::addView 相關調(diào)用棧
WindowManagerImpl.addView()
new ViewRoot
// 保存到 mViews mRoots mParams
ViewRoot.setView(xx)
requestLayout // 檢查主線程
scheduleTraversals
sendEmptyMessage
handleMessage
performTraversals // 2.11 測量 布局 繪制
ViewRoot.relayoutWindow
IWindowSession.relayout // 參考relayout的調(diào)用棧
draw
View.draw
scheduleTralScheduled // try again
mWindowSession.addToDisplay // 2.15 與requestLayout同級
// sWindowSession.add
WMS.addWindow // 2.16
new WindowState //
WindowState.attach //
Session.windowAddedLocked
new SurfaceSession // 開辟一塊內(nèi)存吨枉,由SurfaceFlinger進行混合處理
2.11 測量 布局 繪制流程
performTraversals基本流程
2.12 WindowMangerGlobal::getWindowSession
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager imm = InputMethodManager.getInstance();
IWindowManager windowManager = getWindowManagerService(); // wms
sWindowSession = windowManager.openSession( // 2.13 wms::opensession
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
},
imm.getClient(), imm.getInputContext());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
}
}
2.13 WindowMangerService::openSession
public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
IInputContext inputContext) {
if (client == null) throw new IllegalArgumentException("null client");
if (inputContext == null) throw new IllegalArgumentException("null inputContext");
Session session = new Session(this, callback, client, inputContext);
return session;
}
2.14 WMS::Session與ViewRootImpl關系
Session與ViewRootImpl關系
ViewRootImpl
獲取Session
的代理類,通過Binder::IPC
通信哄芜;Session
持有WMS
服務貌亭;InputState
為事件傳遞相關的類;W
代表當前操作的窗口, 是ViewRootImpl
的內(nèi)部類认臊,且持有ViewRootImpl
的弱引用
2.15 Session::addToDisplay
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
Rect outOutsets, InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outStableInsets, outOutsets, outInputChannel);
}
2.16 WMS::addWindow
/**
* All currently active sessions with clients.
*/
final ArraySet<Session> mSessions = new ArraySet<>();
/**
* Mapping from an IWindow IBinder to the server's Window object.
* This is also used as the lock for all of our state.
* NOTE: Never call into methods that lock ActivityManagerService while holding this object.
*/
final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>();
/**
* Mapping from a token IBinder to a WindowToken object.
*/
final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<>();
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
InputChannel outInputChannel) {
int res = mPolicy.checkAddPermission(attrs, appOp); // PhoneWindowManager進行權限檢查
// 接下來依然是做一些檢查
...
WindowState win = new WindowState(this, session, client, token,
attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
...
mPolicy.adjustWindowParamsLw(win.mAttrs);// 調(diào)整window參數(shù)
...
res = mPolicy.prepareAddWindowLw(win, attrs);
...
win.openInputChannel(outInputChannel); // 窗口端IMS管道
win.attach(); // 2.17
mWindowMap.put(client.asBinder(), win); // 保存到mWindowMap
boolean imMayMove = true;
if (type == TYPE_INPUT_METHOD) {
addInputMethodWindowToListLocked(win);
} else if (type == TYPE_INPUT_METHOD_DIALOG) {
addWindowToListInOrderLocked(win, true);
} else {
addWindowToListInOrderLocked(win, true);
}
...
final WindowStateAnimator winAnimator = win.mWinAnimator;
winAnimator.mEnterAnimationPending = true;
winAnimator.mEnteringAnimation = true;
...
boolean focusChanged = false;
if (win.canReceiveKeys()) {
focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
false /*updateInputWindows*/); // 更新焦點窗口
}
...
if (focusChanged) {
mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
}
mInputMonitor.updateInputWindowsLw(false /*force*/);
}
}
mTokenMap
: 保存所有的顯示令牌, 用于窗口管理;
mWindowMap
:保存所有窗口的狀態(tài)信息(windowstate
), 用于窗口管理;
mSession
:保存當前所有想向WMS尋求窗口管理服務的客戶端;
2.17 WindowState::attach
void attach() {
mSession.windowAddedLocked(); // 2.18
}
2.18 WindowState::windowAddedLocked
void windowAddedLocked() {
if (mSurfaceSession == null) {
mSurfaceSession = new SurfaceSession(); // 在內(nèi)存中創(chuàng)建一塊空間圃庭,用于SurfaceFlinger
mService.mSessions.add(this); //記錄當前Session
if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
mService.dispatchNewAnimatorScaleLocked(this);
}
}
mNumWindow++;
}
3.1 ViewRootImpl::doDie
void doDie() {
checkThread(); // 檢查主線程
synchronized (this) {
mRemoved = true; // 清楚標記
if (mAdded) {
dispatchDetachedFromWindow(); // 3.2 清理窗口的入口
}
if (mAdded && !mFirst) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "destroyHardwareRenderer");
destroyHardwareRenderer();
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
if (mView != null) {
int viewVisibility = mView.getVisibility();
boolean viewVisibilityChanged = mViewVisibility != viewVisibility;
if (mWindowAttributesChanged || viewVisibilityChanged) {
// If layout params have been changed, first give them
// to the window manager to make sure it has the correct
// animation info.
try {
if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
& WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
mWindowSession.finishDrawing(mWindow);
}
} catch (RemoteException e) {
Log.e(mTag, "RemoteException when finish draw window " + mWindow
+ " in " + this, e);
}
}
mSurface.release();
}
}
mAdded = false;
}
WindowManagerGlobal.getInstance().doRemoveView(this); //3.3 移除WindowManagerGlobal中的數(shù)據(jù)
}
3.2 ViewRootImpl::dispatchDetachedFromWindow
void dispatchDetachedFromWindow() {
if (mView != null && mView.mAttachInfo != null) {
mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(false);
mView.dispatchDetachedFromWindow(); //
}
...
mView.assignParent(null);
mView = null;
mAttachInfo.mRootView = null;
mSurface.release(); // surface釋放
if (mInputQueueCallback != null && mInputQueue != null) {
mInputQueueCallback.onInputQueueDestroyed(mInputQueue);
mInputQueue.dispose(); // 事件隊列清理
mInputQueueCallback = null;
mInputQueue = null;
}
if (mInputEventReceiver != null) {
mInputEventReceiver.dispose(); // 輸入事件清理
mInputEventReceiver = null;
}
try {
mWindowSession.remove(mWindow); // 通知wms移除window
} catch (RemoteException e) {
Log.e(mTag, "RemoteException remove window " + mWindow + " in " + this, e);
}
// Dispose the input channel after removing the window so the Window Manager
// doesn't interpret the input channel being closed as an abnormal termination.
if (mInputChannel != null) {
mInputChannel.dispose(); // IMS管道清理
mInputChannel = null;
}
mDisplayManager.unregisterDisplayListener(mDisplayListener);
unscheduleTraversals();
}
3.3 ViewRootImpl::doRemoveView
void doRemoveView(ViewRootImpl root) {
synchronized (mLock) {
final int index = mRoots.indexOf(root);
if (index >= 0) {
mRoots.remove(index);
mParams.remove(index);
final View view = mViews.remove(index);
mDyingViews.remove(view);
}
}
}