【CoCollider】讓系統和應用適配如此簡單

iofomo發表於2024-11-04

在各平臺應用開發過程中,隨著業務的功能增加,不免會涉及到非公開的API依賴,針對某些應用或廠商系統的適配,每個版本都需要投入精力去排查,CoCollider 可以讓我們的適配效率從幾個星期提升到幾小時即可完成。

專案已開源:

☞ Github:https://www.github.com/iofomo/fireyer ☜ 

☞ Github:https://www.github.com/iofomo/wing ☜ 

如果您也喜歡,別忘了給我們點個星。

01. 寫在前面

Android平臺(後續會支援iOS平臺)日常開發過程中,不免會接觸到一些 Hidden(或私有函式和類)的類,JVM層透過反射,Native則透過查詢函式 symbol 來完成。特別是涉及系統Framework層和底層庫較多的實現(特別是安全產品和系統工具類應用),成為每次系統和廠商ROM更新適配的重災區,嚴重影響適配效率。

以往,開發同學要麼先一個個自行排查程式碼後再提交測試,這個過程重複,耗時且容易遺漏。要麼先讓測試同學先進行用例覆蓋測試,然後開發同學透過BUG來進行分析,這會導致整個團隊效率更加低下。

由於我們虛擬化產品的特性,工程中涉及系統和應用適配的介面眾多,工作量很大,主要有兩部分:

  1. 如何快速尋找到系統新增的模組,感興趣的可以檢視我們的另一個開源專案 【ASeeker】 https://www.github.com/iofomo/aseeker
  2. 如何快速定位現有使用的API是否已發生變化,這就是【CoCollider】 要解決的問題。

CoCollider 已經在我們內部使用,極大提升我們系統適配效率,原本需要幾個星期的工作量,現在只需幾小時便可適配完成,原理簡單,堪稱適配效率神器。Android 15釋出在即,現在分享給大家。

CoCollider同樣適用於其他平臺(如:iOS)和某些深度定製的應用版本適配。

02. 我們需要

對於系統的API,我們的需求是:

  1. 類的屬性是否有變化。
  2. 類的成員屬性是否有變化。
  3. 類的方法屬性是否有變化。
  4. Native庫和函式是否存在。

對於開發工程師的工作量,首次需要在原始碼中新增註釋標籤,這個工作不可省略,卻一勞永逸。後續需要在每次涉及適配的程式碼處加上@CoCollider標籤就行。

Java程式碼標籤格式:

格式:
// @CoCollider {class name},{-/+}{field name/method name},...

範例:
# 僅檢視類是否變更
// @CoCollider android.utils.Abc
# 僅檢視類所有成員是否變更
// @CoCollider android.utils.Abc,-*
# 檢視類和某成員或方法是否變更(支援多個)
// @CoCollider android.utils.Abc,-mFile
// @CoCollider android.utils.Abc,-mFile,mName
// @CoCollider android/utils/Abc,-mFile
// @CoCollider android.utils.Abc,+getFile,-mName
// @CoCollider android/utils/Abc,+getFile,+getName,-mName

# 支援預設自動填充:(按照順序依次填充)
Class.forName("android.utils.Abc");// @CoCollider
# 等同於:// @CoCollider android.utils.Abc

ReflectUtils.getStaticField("android.utils.Abc", "mName");// @CoCollider ,-
# 等同於:// @CoCollider android.utils.Abc,-mName

Native 程式碼標籤格式:

格式:
// @CoCollider ~{lib name},{-/+}{field name/method name},...
  
範例:
# 檢視方法是否變更
// @CoCollider ~libc.so,+open
// @CoCollider ~/system/lib/libc.so,+open
// @CoCollider ~/system/lib/libc.so,+open,+close

# 支援預設自動填充:(按照順序依次填充)
utils_dlsym("libc.so", "open");// @CoCollider ~,+
# 等同於:// @CoCollider ~libc.so,+open

utils_dlsym("open");// @CoCollider ~libc.so,+
# 等同於:// @CoCollider ~libc.so,+open

03. 配置執行

  1. 電腦下載配置wing

  2. 手機安裝Fireyer,或整合CoCollider模組的應用,連結adb

  3. 掃描程式碼:

    # 命令格式:掃描當前目錄下的程式碼(預設支援 h/c/cpp/java/kt/aidl,也可以追加檔案型別)
    $ wing -cocollider scan
    $ wing -cocollider scan /home/space
    # 或
    $ python ./cocollider.py scan
    $ python ./cocollider.py scan /home/space
    # 在當前目錄輸出結果
    >>> cocollider-scan-20241023-112044.txt
    
  4. 解析執行:

    # 命令格式:呼叫 Fireyer 應用
    $ wing -cocollider run /home/cocollider-scan-20241023-112044.txt
    # 或
    $ python ./cocollider.py run /home/cocollider-scan-20241023-112044.txt
    
    # 在當前目錄輸出結果
    >>> cocollider-run-20241023-112044.txt
    
  5. 使用對比工具檢視結果即可快速定位變更內容。

04. 掃描結果

cocollider-scan-20241023-112044.txt 中的檔案內容為:

############################################################
= android.utils.Abc

- mFile
> application/fireyer/test/test1.java,14

- mName3
> application/fireyer/test/test1.java,14

- mPath
> application/fireyer/test/test1.java,14

############################################################
= android.utils.Abc1

- mFile
> application/fireyer/test/test1.java,5

...

05. 執行結果

cocollider-run-20241023-112044.txt 中的檔案內容(已對classlib庫,functionfieldmethod排序,便於使用對比工具對比)

############################################################
~ libwilhelm.so
[OK]

+ _ZN7androidxx6BufferE
[OK], public final class libcore.io.Linux
> cmpt/xxx/jni/xxx/jni/src/xxx.cpp,362

+ _ZN7android1xx6BufferE
[OK], public final class libcore.io.Linux
> cmpt/xxx/jni/xxx/jni/src/xxx.cpp,350


############################################################
= ohos.abilityshell.HarmonyApplication
[Fail]

- applicationHandler
[Fail]
> scene/xxx/xxx.java,36


############################################################
= ohos.system.Parameters
[Fail]

+ nativeGet
[Fail]
> scene/xxx.cpp,250

...

06. 對比結果

分別在不同版本系統執行 python cocollider.py run 之後,使用對比工具(如:Beyond Compare)對內容進行比較檢視,可以快速找到新增,修改和刪除項,從而可以快速進行排查和修復。

相關文章