Activity Window WMS的源碼關(guān)系流程介紹

system_server_AMS類圖.png
Activity_Window_相關(guān)類圖.png
system_server_AMS類圖.png
總體類圖.png

流程圖.png

一欢策、相關(guān)概念
1、ActivityThread:為應(yīng)用程序的主線程類,所有的APK程序都有且僅有一個(gè)ActivityThread掠哥,程序的入口為該類static main()函數(shù)
Activity:Activity包含一個(gè)Window,該Window在Activity的attach方法中通過調(diào)用new PhoneWindow()創(chuàng)建一個(gè)window;
2稚叹、PhoneWindow:繼承Window類,是把一個(gè)FrameLayout進(jìn)行一定的包裝拿诸,并提供了一組通用的窗口操作接口扒袖,內(nèi)部包含一個(gè)DecorView
3、View:最基本的UI組件亩码,表示屏幕上的一個(gè)矩形區(qū)域季率;
4、DecorView:該類是一個(gè) FrameLayout 的子類蟀伸,并且是 PhoneWindow 中的一個(gè)內(nèi)部類蚀同。Decor的英文是 Decoration缅刽,即“修飾”的意思,DecorView 就是對(duì)普通的 FrameLayout 進(jìn)行了一定的修飾蠢络,比如添加一個(gè)通用的 Title bar衰猛,并響應(yīng)特定的按鍵消息等。刹孔;
5啡省、Window:表示頂層窗口,管理界面的顯示和事件的響應(yīng)髓霞;每個(gè)Activity 均會(huì)創(chuàng)建一個(gè)PhoneWindow對(duì)象卦睹,是Activity和整個(gè)View系統(tǒng)交互的接口,該類提供了一組通用的窗口(Window)操作 API方库,這里的窗口僅僅是程序?qū)用嫔系慕嵝颍琖MS 所管理的窗口并不是 Window 類,而是一個(gè) View 或者 ViewGroup 類纵潦,一般就是指DecorView 類徐鹤,即一個(gè) DecorView 就是 WmS 所管理的一個(gè)窗口。Window 是一個(gè) abstract 類型邀层。
6返敬、WindowManager:一個(gè)interface,繼承自ViewManager寥院。所在應(yīng)用進(jìn)程的窗口管理器劲赠;有一個(gè)implementation WindowManagerImpl;
主要用來管理窗口的一些狀態(tài)秸谢、屬性凛澎、view增加、刪除估蹄、更新预厌、窗口順序、消息收集和處理等元媚。
7、ViewRootImpl:通過IWindowSession接口與全局窗口管理器進(jìn)行交互:界面控制和消息響應(yīng)苗沧;WMS 管理客戶端窗口時(shí)刊棕,需要通知客戶端進(jìn)行某種操作,這些都是通過異步消息完成的
二待逞、步驟
Step1:
當(dāng)啟動(dòng)Activity時(shí)甥角,system_server進(jìn)程通過AMS(ActivityManagerService)的遠(yuǎn)程代理ApplicationThreadProxy(即應(yīng)用進(jìn)程的Binder,IApplicationThread)的scheduleLaunchActivit(),標(biāo)示SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION识樱,底層binder驅(qū)動(dòng)啟動(dòng)應(yīng)用進(jìn)程XXXActivity嗤无,到應(yīng)用進(jìn)程的ActivityThread的內(nèi)部類ApplicationThread的父類ApplicationNative的onTransact震束,再到scheduleLaunchActivity().
Step2:
ApplicationThread的scheduleLaunchActivity:通過sendMessage(H.LAUNCH_ACTIVITY, r),發(fā)到UI線程的ActivityThread 的H處理即handleLaunchActivity:
ActivityThread.java

    public final class ActivityThread {
      private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        // Initialize before creating the activity
        WindowManagerGlobal.initialize();
        Activity a = performLaunchActivity(r, customIntent);
        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
        ...
        } 
    }
}

其中WindowManagerGlobal.initialize;是先取到WMS(WindowManagerService)的遠(yuǎn)程代理IWindowManager

WindowManagerGlobal.java

public final class WindowManagerGlobal {
    public static void initialize() {
        getWindowManagerService();
    }
    public static IWindowManager getWindowManagerService() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowManagerService == null) {
                sWindowManagerService = IWindowManager.Stub.asInterface(
                        ServiceManager.getService("window"));
                try {
                    sWindowManagerService = getWindowManagerService();
                    ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowManagerService;
        }
    }
}

Activity a = performLaunchActivity(r, customIntent);使用ClassLoader加載XXXActivity当犯,這其中會(huì)創(chuàng)建ContextImpl垢村、如果Application還沒啟動(dòng)過,會(huì)先把Applicaition創(chuàng)建并onCreate,然后調(diào)用XXXActivity的attach();
在attach中:會(huì)創(chuàng)建改activity的對(duì)應(yīng)的window即PhoneWindow嚎卫,以及phoneWindow和WindowManagerImpl關(guān)聯(lián):
Activity:

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);
        mFragments.attachHost(null /*parent*/);
        mWindow = new PhoneWindow(this, window);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        mMainThread = aThread;
        mInstrumentation = instr;
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;
}

其中:(WindowManager)context.getSystemService(Context.WINDOW_SERVICE)獲取到是WindowManagerImpl:
這邊會(huì)走到ContextImpl.getSystemService:

class ContextImpl extends Context {   
  @Override
    public Object getSystemService(String name) {
        return SystemServiceRegistry.getSystemService(this, name);
    }
}

SystemServiceRegistry:

final class SystemServiceRegistry {
  public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }
  private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
            new HashMap<Class<?>, String>();
    private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
            new HashMap<String, ServiceFetcher<?>>();
    private static int sServiceCacheSize;
    static {
        registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
                new CachedServiceFetcher<AccessibilityManager>() {
            @Override
            public AccessibilityManager createService(ContextImpl ctx) {
                return AccessibilityManager.getInstance(ctx);
            }});
    registerService(Context.WINDOW_SERVICE, WindowManager.class,
                new CachedServiceFetcher<WindowManager>() {
            @Override
            public WindowManager createService(ContextImpl ctx) {
                return new WindowManagerImpl(ctx);
            }});
}

返回是new WindowManagerImpl(ctx);在performLaunchActivity函數(shù)中嘉栓,走完attach后,繼續(xù)調(diào)用mInstrumentation.callActivityOnCreate去實(shí)行XXXActivity的onCreate拓诸,這時(shí)候大家會(huì)寫setContentView(R.layout.xxx)
Step3:
Activity.setContentView():
會(huì)調(diào)用getWindow().setContentView(layoutResID),即PhoneWindow類中的setContentView:主要是在PhoneWindow創(chuàng)建DecorView mDecor(This is the top-level view of the window, containing the window decor),然后從mDecor找出android.R.id.content: mContentParent(ViewGroup), 然后把a(bǔ)ctivity設(shè)置的View添加到mContentParent.addView(view, params);

public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
}

PhoneWindow:

public class PhoneWindow extends Window implements MenuBuilder.Callback {
  public void setContentView(int layoutResID) {
        
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }
}

Step4:
在ActivitThread.handleLaunchActivity函數(shù)走完performLaunchActivity后侵佃,接著走h(yuǎn)andleResumeActivity函數(shù)中,顯示啟動(dòng)r = performResumeActivity(token, clearHide, reason);去走XXXActivity的onResume奠支。
接著會(huì)對(duì)Activity的對(duì)應(yīng)的window設(shè)置窗口類型:l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION馋辈,WMS是對(duì)窗口進(jìn)行操作,每個(gè)activity對(duì)應(yīng)一個(gè)窗口倍谜,F(xiàn)ramework會(huì)定義好幾種窗口類型迈螟,比如系統(tǒng)Window、應(yīng)用程序window枢劝、子Window等井联。這邊的type類型很重要,沒有這個(gè)您旁,window顯示不出來的烙常。
接著會(huì)調(diào)用到ViewManager wm = a.getWindowManager();wm.addView(decor, l);走到WindowManagerImpl.addView:
ActivityThread:

final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        ...
        r = performResumeActivity(token, clearHide, reason);
        ...
            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (r.mPreserveWindow) {
                    a.mWindowAdded = true;
                    r.mPreserveWindow = false;
                   
                    ViewRootImpl impl = decor.getViewRootImpl();
                    if (impl != null) {
                        impl.notifyChildRebuilt();
                    }
                }
                if (a.mVisibleFromClient && !a.mWindowAdded) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }
             ...
    }

Step5:
WindowManagerImpl的addView又調(diào)用到WindowManagerGlobal.getInstance()的addView:
這個(gè)函數(shù)會(huì)創(chuàng)建root = new ViewRootImpl(view.getContext(), display);然后保存到mRoots.add(root)
接著調(diào)用到 root.setView(view, wparams, panelParentView);

public final class WindowManagerImpl implements WindowManager {
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
    }
}

public final class WindowManagerGlobal {
    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
        ...
        ViewRootImpl root;
        View panelParentView = null;
        synchronized (mLock) {
            ...
            root = new ViewRootImpl(view.getContext(), display);
            view.setLayoutParams(wparams);
            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);
        }
        // do this last because it fires off messages to start doing things
        try {
            root.setView(view, wparams, panelParentView);
        } catch (RuntimeException e) {
           
        }
    }
}

Step6:
ViewRootImpl.setView():
這個(gè)函數(shù)中,通過WindowManagerGloabl拿到IWindowSession mWindowSession及遠(yuǎn)程WMS的Seesion的對(duì)象鹤盒,進(jìn)行mWindowSession.addToDisplay蚕脏,到system_server進(jìn)程的Session中。

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks {
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
                ....
                try {
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mInputChannel);
                }            
            }
        ...
    }
}

這個(gè)mWindowSession是

public static IWindowSession getWindowSession() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    InputMethodManager imm = InputMethodManager.getInstance();
                    IWindowManager windowManager = getWindowManagerService();
                    sWindowSession = windowManager.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;
        }
    }

調(diào)用到WindowManagerService的openSession方法:

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
   @Override
    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;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末侦锯,一起剝皮案震驚了整個(gè)濱河市驼鞭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌尺碰,老刑警劉巖挣棕,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異亲桥,居然都是意外死亡洛心,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門题篷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來词身,“玉大人,你說我怎么就攤上這事番枚》ㄑ希” “怎么了损敷?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長深啤。 經(jīng)常有香客問我拗馒,道長,這世上最難降的妖魔是什么墓塌? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任瘟忱,我火速辦了婚禮,結(jié)果婚禮上苫幢,老公的妹妹穿的比我還像新娘肪笋。我一直安慰自己耕蝉,他們只是感情好街夭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布祸轮。 她就那樣靜靜地躺著,像睡著了一般哀峻。 火紅的嫁衣襯著肌膚如雪涡相。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天剩蟀,我揣著相機(jī)與錄音催蝗,去河邊找鬼。 笑死育特,一個(gè)胖子當(dāng)著我的面吹牛丙号,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播缰冤,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼犬缨,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了棉浸?” 一聲冷哼從身側(cè)響起怀薛,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎迷郑,沒想到半個(gè)月后枝恋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嗡害,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年鼓择,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片就漾。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖念搬,靈堂內(nèi)的尸體忽然破棺而出抑堡,到底是詐尸還是另有隱情摆出,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布首妖,位于F島的核電站偎漫,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏有缆。R本人自食惡果不足惜象踊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望棚壁。 院中可真熱鬧杯矩,春花似錦、人聲如沸袖外。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽曼验。三九已至泌射,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鬓照,已是汗流浹背熔酷。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留豺裆,地道東北人拒秘。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像留储,于是被迫代替她去往敵國和親翼抠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容