<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>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                前文講述的內容都集中在Java層,下面要按照流程順序分析JNI層的內容。 1. Surface的無參構造分析 在JNI層,第一個被調用的是Surface的無參構造函數,其代碼如下所示: **Surface.java** ~~~ public Surface() { ...... //CompatibleCanvas從Canvas類派生 mCanvas = new CompatibleCanvas(); } ~~~ Canvas是什么?根據SDK文檔的介紹可知,畫圖需要“四大金剛”相互合作,這四大金剛是: - Bitmap:用于存儲像素,也就是畫布。可把它當做一塊數據存儲區域。 - Canvas:用于記載畫圖的動作,比如畫一個圓,畫一個矩形等。Canvas類提供了這些基本的繪圖函數。 - Drawing primitive:繪圖基元,例如矩形、圓、弧線、文本、圖片等。 - Paint:它用來描述繪畫時使用的顏色、風格(如實線、虛線等)等。 在一般情況下,Canvas會封裝一塊Bitmap,而作圖就是基于這塊Bitmap的。前面說的畫布,其實指的就是Canvas中的這塊Bitmap。 這些知識稍了解即可,不必去深究。Surface的無參構造函數沒有什么有價值的內容,接著看下面的內容。 2. SurfaceSession的構造 現在要分析的是SurfaceSession,其構造函數如下所示: **SurfaceSession.java** ~~~ public SurfaceSession() { init();//這是一個native函數 } ~~~ init是一個native函數。去看看它的JNI實現,它在android_view_Surface.cpp中,代碼如下所示: **android_view_Surface.cpp** ~~~ static void SurfaceSession_init(JNIEnv* env,jobject clazz) { //創建一個SurfaceComposerClient對象 sp<SurfaceComposerClient> client = new SurfaceComposerClient; client->incStrong(clazz); //在Java對象中保存這個client對象的指針,類型為SurfaceComposerClient env->SetIntField(clazz, sso.client, (int)client.get()); } ~~~ 這里先不討論SurfaceComposerClient的內容,擬繼續把乾坤大挪移的流程走完。 3. Surface的有參構造 下一個調用的是Surface的有參構造,其參數中有一個SurfaceSession。先看Java層的代碼,如下所示: **Surface.java** ~~~ publicSurface(SurfaceSession s,//傳入一個SurfaceSession對象 int pid, String name, int display, int w, int h, int format, int flags) throws OutOfResourcesException { ...... mCanvas = new CompatibleCanvas(); //又一個native函數,注意傳遞的參數:display以后再說,w,h代表繪圖區域的寬高值 init(s,pid,name,display,w,h,format,flags); mName = name; } ~~~ Surface的native init函數的JNI實現,也在android_view_Surface.cpp中,一起來看: **android_view_Surface.cpp** ~~~ static void Surface_init( JNIEnv*env, jobject clazz, jobject session, jint pid, jstring jname, jint dpy, jint w, jint h, jint format, jintflags) { //從SurfaceSession對象中取出之前創建的那個SurfaceComposerClient對象 SurfaceComposerClient* client = (SurfaceComposerClient*)env->GetIntField(session, sso.client); sp<SurfaceControl> surface;//注意它的類型是SurfaceControl if (jname == NULL) { /* 調用SurfaceComposerClient的createSurface函數,返回的surface是一個 SurfaceControl類型。 */ surface = client->createSurface(pid, dpy, w, h, format, flags); } else{ ...... } //把這個surfaceControl對象設置到Java層的Surface對象中,對這個函數就不再分析了 setSurfaceControl(env, clazz, surface); } ~~~ 4. copyFrom的分析 現在要分析的就是copyFrom了。它就是一個native函數。看它的JNI層代碼: **android_view_Surface.cpp** ~~~ static void Surface_copyFrom(JNIEnv* env,jobject clazz, jobject other) { //根據JNI函數的規則,clazz是copyFrom的調用對象,而other是copyFrom的參數。 //目標對象此時還沒有設置SurfaceControl,而源對象在前面已經創建了SurfaceControl constsp<SurfaceControl>& surface = getSurfaceControl(env, clazz); constsp<SurfaceControl>& rhs = getSurfaceControl(env, other); if (!SurfaceControl::isSameSurface(surface, rhs)) { //把源SurfaceControl對象設置到目標Surface中。 setSurfaceControl(env, clazz, rhs); } } ~~~ 這一步還是比較簡單的,下面看第五步writeToParcel函數的調用。 5. writeToParcel的分析 多虧了必殺技aidl工具的幫忙,才挖出這個隱藏的writeToParcel函數調用,下面就來看看它,代碼如下所示: **android_view_Surface.cpp** ~~~ static void Surface_writeToParcel(JNIEnv* env,jobject clazz, jobject argParcel, jint flags) { Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel); //clazz就是Surface對象,從這個Surface對象中取出保存的SurfaceControl對象 const sp<SurfaceControl>&control(getSurfaceControl(env, clazz)); /* 把SurfaceControl中的信息寫到Parcel包中,然后利用Binder通信傳遞到對端, 對端通過readFromParcel來處理Parcel包。 */ SurfaceControl::writeSurfaceToParcel(control, parcel); if (flags & PARCELABLE_WRITE_RETURN_VALUE) { //還記得PARCELABLE_WRITE_RETURN_VALUE嗎?flags的值就等于它 //所以本地Surface對象的SurfaceControl值被置空了 setSurfaceControl(env, clazz, 0); } } ~~~ 6. readFromParcel的分析 再看作為客戶端的ViewRoot所調用的readFromParcel函數。它也是一個native函數,JNI層的代碼如下所示: **android_view_Surface.cpp** ~~~ static void Surface_readFromParcel(JNIEnv* env, jobject clazz, jobject argParcel) { Parcel* parcel = (Parcel*)env->GetIntField( argParcel,no.native_parcel); //注意下面定義的變量類型是Surface,而不是SurfaceControl const sp<Surface>&control(getSurface(env, clazz)); //根據服務端傳遞的Parcel包來構造一個新的surface。 sp<Surface> rhs = new Surface(*parcel); if (!Surface::isSameSurface(control, rhs)) { //把這個新surface賦給ViewRoot中的mSurface對象。 setSurface(env,clazz, rhs); } } ~~~ 7. Surface乾坤大挪移的小結 可能有人會問,乾坤大挪移怎么這么復雜?這期間出現了多少對象?來總結一下,在此期間一共有三個關鍵對象(注意我們這里只考慮JNI層的Native對象),它們分別是: - SurfaceComposerClient。 - SurfaceControl。 - Surface,這個Surface對象屬于Native層,和Java層的Surface相對應。 其中轉移到ViewRoot成員變量mSurface中的,就是最后這個Surface對象了。這一路走來,真是異常坎坷。來回顧并概括總結一下這段歷程。至于它的作用應該是很清楚了。以后要破解SurfaceFlinger,靠的就是這個精簡的流程。 - 創建一個SurfaceComposerClient。 - 調用SurfaceComposerClient的createSurface得到一個SurfaceControl對象。 - 調用SurfaceControl的writeToParcel把一些信息寫到Parcel包中。 - 根據Parcel包的信息構造一個Surface對象。這個Surface對象保存到Java層的mSurface對象中。這樣,大挪移的結果是ViewRoot得到一個Native的Surface對象。 >[info] **注意**:精簡流程后,寥寥數語就可把過程說清楚。以后我們在研究代碼時,也可以采取這種方式。 這個Surface對象非常重要,可它到底有什么用呢?這正是下一節要講的內容。
                  <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>

                              哎呀哎呀视频在线观看