<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                1. 乾坤大挪移的表象 relayout的函數是一個跨進程的調用,由WMS完成實際處理。先到ViewRoot中看看調用方的用法,代碼如下所示: **ViewRoot.java** ~~~ private intrelayoutWindow(WindowManager.LayoutParams params, int viewVisibility, boolean insetsPending) throws RemoteException { int relayoutResult = sWindowSession.relayout( mWindow, params, (int) (mView.mMeasuredWidth * appScale + 0.5f), (int) (mView.mMeasuredHeight * appScale + 0.5f), viewVisibility, insetsPending, mWinFrame, mPendingContentInsets, mPendingVisibleInsets, mPendingConfiguration, mSurface);//mSurface傳了進去 ...... return relayoutResult; } ~~~ 再看接收方的處理。它在WMS的Session中,代碼如下所示: **WindowManagerService.java::Session** ~~~ public int relayout(IWindow window,WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, boolean insetsPending, Rect outFrame, Rect outContentInsets, Rect outVisibleInsets, Configuration outConfig, Surface outSurface) { //注意最后這個參數的名字,叫outSurface //調用外部類對象的relayoutWindow returnrelayoutWindow(this, window, attrs, requestedWidth,requestedHeight, viewFlags, insetsPending, outFrame, outContentInsets,outVisibleInsets, outConfig, outSurface); } ~~~ **WindowManagerService.java** ~~~ public int relayoutWindow(Session session,IWindow client, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, boolean insetsPending, Rect outFrame, Rect outContentInsets, Rect outVisibleInsets, Configuration outConfig, SurfaceoutSurface){ ..... try { //win就是WinState,這里將創建一個本地的Surface對象 Surfacesurface = win.createSurfaceLocked(); if(surface != null) { //先創建一個本地surface,然后在outSurface的對象上調用copyFrom //將本地Surface的信息拷貝到outSurface中,為什么要這么麻煩呢? outSurface.copyFrom(surface); ...... } ~~~ **WindowManagerService.java::WindowState** ~~~ Surface createSurfaceLocked() { ...... try { //mSurfaceSession就是在Session上創建的SurfaceSession對象 //這里,以它為參數,構造一個新的Surface對象 mSurface = new Surface( mSession.mSurfaceSession, mSession.mPid, mAttrs.getTitle().toString(), 0, w, h, mAttrs.format, flags); } Surface.openTransaction();//打開一個事務處理 ...... Surface.closeTransaction();//關閉一個事務處理。關于事務處理以后再分析 ...... } ~~~ 上面的代碼段好像有點混亂。用圖8-7來表示一下這個流程: :-: ![](http://img.blog.csdn.net/20150802162309594?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖8-7 復雜的Surface創建流程 根據圖8-7可知: - WMS中的Surface是乾坤中的乾,它的構造使用了帶SurfaceSession參數的構造函數。 - ViewRoot中的Surface是乾坤中的坤,它的構造使用了無參構造函數。 - copyFrom就是挪移,它將乾中的Surface信息,拷貝到坤中的Surface即outSurface里。 要是覺得乾坤大挪移就是這兩三下,未免就太小看它了。為徹底揭示這期間的復雜過程,我們將使用必殺技——aidl工具。 2. 揭秘Surface的乾坤大挪移 aidl可以把XXX.aidl文件轉換成對應的Java文件。剛才所說的乾坤大挪移發生在ViewRoot調用IWindowSession的relayout函數中,它在IWindowSession.adil中的定義如下: **IWindowSesson.aidl** ~~~ nterface IWindowSession { ...... intrelayout(IWindow window, in WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, boolean insetsPending, out Rect outFrame, out Rect outContentInsets, out Rect outVisibleInsets, out Configuration outConfig, out Surface outSurface); ~~~ 下面,拿必殺技aidl來編譯一下這個aidl文件,其使用方法如下: ~~~ 在命令行下可以輸入: aidl –Ie:\froyo\source\frameworks\base\core\java\ -Ie:\froyo\source\frameworks\base\Graphics\java e:\froyo\source\frameworks\base\core\java\android\view\IWindowSession.aidltest.java 新生成的Java文件叫test.java。其中,-I參數指定include目錄,例如aidl文件中使用了別的Java文件中的類,所以需要指定這些Java文件所在的目錄。 ~~~ 先看ViewRoot這個客戶端生成的代碼,如下所示: **test.java::Bp端::relayout** ~~~ public int relayout(android.view.IWindow window, android.view.WindowManager.LayoutParams attrs, int requestedWidth, intrequestedHeight, int viewVisibility, boolean insetsPending, android.graphics.Rect outFrame, android.graphics.Rect outContentInsets, android.graphics.Rect outVisibleInsets, android.content.res.Configuration outConfig, android.view.Surface outSurface)//outSurface是第11個參數 throwsandroid.os.RemoteException { android.os.Parcel_data = android.os.Parcel.obtain(); android.os.Parcel_reply = android.os.Parcel.obtain(); int_result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeStrongBinder((((window!=null))?(window.asBinder()):(null))); if((attrs!=null)) { _data.writeInt(1); attrs.writeToParcel(_data,0); } else { _data.writeInt(0); } _data.writeInt(requestedWidth); _data.writeInt(requestedHeight); _data.writeInt(viewVisibility); _data.writeInt(((insetsPending)?(1):(0))); //奇怪,outSurface的信息沒有寫到請求包_data中,就直接發送請求消息了 mRemote.transact(Stub.TRANSACTION_relayout,_data, _reply, 0); _reply.readException(); _result= _reply.readInt(); if((0!=_reply.readInt())) { outFrame.readFromParcel(_reply); } .... if((0!=_reply.readInt())) { outSurface.readFromParcel(_reply);//從Parcel中讀取信息來填充outSurface } } ...... return_result; } ~~~ 奇怪!ViewRoot調用requestlayout竟然沒有把outSurface信息傳進去,這么說,服務端收到的Surface對象應該就是空吧?那怎么能調用copyFrom呢?還是來看服務端的處理,先看首先收到消息的onTransact函數,代碼如下所示: **test.java::Bn端::onTransact** ~~~ public boolean onTransact(int code,android.os.Parcel data, android.os.Parcelreply, int flags) throwsandroid.os.RemoteException { switch(code) { caseTRANSACTION_relayout: { data.enforceInterface(DESCRIPTOR); android.view.IWindow_arg0; android.view.Surface_arg10; //剛才講了,Surface信息并沒有傳過來,那么在relayOut中看到的outSurface是怎么 //出來的呢?看下面這句可知,原來在服務端這邊竟然new了一個新的Surface!!! _arg10= new android.view.Surface(); int_result = this.relayout(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5,_arg6, _arg7, _arg8, _arg9, _arg10); reply.writeNoException(); reply.writeInt(_result); //_arg10就是調用copyFrom的那個outSurface,那怎么傳到客戶端呢? if((_arg10!=null)) { reply.writeInt(1); //調用Surface的writeToParcel,把信息寫到reply包中。 //注意最后一個參數為PARCELABLE_WRITE_RETURN_VALUE _arg10.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } } ...... returntrue; } ~~~ 看完這個,會讓人有點毛骨悚然。我最開始一直在JNI文件中尋找大挪移的蹤跡,但有幾個關鍵點始終不能明白,萬不得已就使用了這個aidl必殺技,于是終于揭露出其真相了。 3. 乾坤大挪移的真相 這里,總結一下乾坤大挪移的整個過程,如圖8-8表示: :-: ![](http://img.blog.csdn.net/20150802162245458?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖8-8 乾坤大挪移的真面目 上圖非常清晰地列出了乾坤大挪移的過程,我們可結合代碼來加深理解。 >[info] **注意**,這里,將BpWindowSession作為了IWindowSessionBinder在客戶端的代表。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看