從軟體工程的角度,談模組為什麼總是不相容

魂祈梦發表於2024-11-26

前言

今天剛刷上Apatch,發現其沒有提供Zygisk,又去酷安搜了一搜,似乎有人反應刷Lsposed不起作用,大致瞭解了一下,並查了些資料。下面我開始猜測以及進行理論。
說是從軟體工程出發,但是實際上我並不算一個好學生,更無法代表軟體工程,這或許很標題黨,但是我確實想以這個名稱命名。

一言蔽之,Apatch和KernelSu之類的本來就只是Root解決方案,只不過Magisk太流行了,如果不對magisk模組進行一些相容,沒人會去使用KernelSu之類的軟體。事實上直到如今,Root管理器中佔有率最高的依然是面具。

鋪墊

在此之前,我們可以說一說介面和繼承這個老生常談的問題。當然,我無法代表軟體工程,所有的見解只是個人思考和猜測,甚至很可能出現大量錯誤,權當我胡說,當個笑話看看就好。
我說說我對介面和繼承的簡單理解。
繼承:"普通人類和機器人都是人"。
介面:"小米手機和OPPO手機都是手機"。

這個例子也許不是很好,我其實在盡力地使這篇文章變得有趣起來,我想表達的是,繼承通常是允許擴充套件的,允許新增新功能的,而介面我們通常不允許擴充套件,該有什麼功能就應該實現什麼功能。至於怎麼實現和如何實現,我不管你。

從程式碼的編寫上來說,繼承通常是允許新的方法出現的,他允許子類(派生類)擁有其他子類未擁有的方法,大家可以有非常多的不同點。
而介面不同,我們通常實現介面都是隻實現介面所約定的方法,而不去寫新的方法,除非我們讓這個類去同時實現另一個介面。或者換句話來說,介面不關心其他的方法。

對於不熟悉程式碼的同學,我們可以簡單的把介面理解為功能,而父類子類簡單理解為父與子。

事實上介面完全允許其他的方法存在,但是大家都不太會去為一個實現了介面的類實現介面之外的方法。原因也很簡單,因為單一職責原則

為什麼

說到這裡,我的用意就很明顯了,各個root管理器更像是繼承了某個父類的不同子類,而非實現介面。

其實既不是繼承也不是介面,因為他們的開發者本就不同,根本就沒有進行約定的義務,他們愛寫什麼寫什麼,你管不著。

早期,我們只希望擁有root管理器,SuperSu就是這個需求的一種實現。
image

後來,supersu不更新了,不支援新的系統,於是magisk出現了。
很遺憾我並不清楚magisk的完整歷史,但是假設magisk初期就提供了模組化支援。(至少我接觸的時候就已經有模組了)
模組是個好東西,magisk出現就佔據了大量市場,大家都對magisk讚不絕口。
此時我們再假設,假如歷史長河中,出現了一款名為UltraSu(neta SuperSu)的軟體,他提供外掛化支援,就像瀏覽器外掛那樣。由於二者出現時間相近,而當時大家的需求是root,從來沒想過模組的問題。
那麼magisk模組和UltraSu互不相容就是可以預想的事情了,到這裡我的核心思想已經表現出來了。你自然可以丟下這篇文章不管。

不過我可要繼續說下去了。
大家都知道,根本沒有UltraSu這個東西,至少有很長一段時間,大家都在使用magisk而不是什麼別的管理器。
magisk也衍生出了別的版本,廣為人知的就是Alpha和Delta(現在叫kitsume)。
vvb2060https://github.com/vvb2060
Alpha的作者自不必多說,我認識面具的時候隱隱約約就知道他是面具的維護者之一,而且他還是Lsposed的維護者。
image
那麼相容性好是可以預見的。
delta我其實不太清楚,無論如何,相容性應該也不會比Alpha好。

如果再說回前面的繼承和介面,這倆就類似繼承,他們從magisk分支出來,提供了新的功能。

扯遠了,讓我們再拉回時間線,現在magisk火的一塌糊塗,在那之前,還有一款軟體也很火爆。

xposed

我不太清楚xposed是什麼時候流行起來的(遠古級xp模組上帝模式,他在這個時期非常受歡迎,哪怕是edxp時期),但是這對本文沒什麼影響。我們假設xposed和magisk是近乎同時流行的。(印象中xposed更早)
這時,magisk和xposed還是互不相干的兩個專案。發展了一段時間,大家的需求變成了root以及xposed模組,由於magisk的流行,大家也離不開magisk模組了。
這時候大家的需求如下:
0. 不修改system(最早由面具實現了)

  1. root(SuperSu時期就已經實現,更早的不考慮)
  2. xposed模組
  3. magisk模組
  4. 隱藏root等一系列環境?
    於是,不知何時,EdXposed出現了。
    專案地址
    https://github.com/ElderDrivers/EdXposed
    他的出現主要解決的問題就是,如何在不修改系統的情況下,使用xposed框架。至於系統相容性是順帶解決的,EdXposed透過刷入Ruri模組(提供執行環境),實現了Xposed框架實現的功能,與此同時,由於模組不修改系統,需求完美地解決了。

其實這時候我才初步接觸Xposed。至少當我認識Edxp的時候,他已經是使用模組的方式安裝了,早期xposed是用installer安裝的,和magisk沒有什麼交集。

Edxp同樣非常流行,可以說是一統江湖,直接替代了xposed。
印象中,SuperSu+Xposed -> Magisk + Edxposed。
而後某一天,LSPosed出現了,他的出現讓人意外,因為他的出現不是由市場催生的,而是由社群呼籲而成。(還是僅為猜測)
EdXposed和原來的Xposed都存在一個問題,無論目標應用是否正在執行,xposed的環境都會注入,這會導致效能問題,因此,Lsposed實現了作用域功能,使得模組僅對某些應用生效。

我合理地進行猜測,早期Lsposed使用Ruri提供環境注入。(官方術語為zygote)
而後期,Magisk專案提供了Zygisk(zygote注入的一種實現,Zygisk的目的是隱藏Root環境,也就是MagiskHide),於是Lsposed也去適配Zygisk。

下圖為Lsposed在github的更新日誌,
image
再後來,Magisk的作者topjohnwu https://github.com/topjohnwu
他被谷歌收編,雖然能夠繼續開發Magisk,但是似乎不被允許更新Zygisk。
相近地,KernelSu等框架橫空出世,他們沒有Zygisk之類的注入環境,如果使用者需要使用Lsp等xp框架,KernelSu沒有辦法。
這也是Zygisk Next https://github.com/Dr-TSNG/ZygiskNext 出現的原因

作者
https://github.com/Dr-TSNG
(他曾參與Lsposed的開發)
下面這張圖是開了網頁翻譯(考慮到文章的可讀性)
image

他的出現間接地幫助了所有的Root管理器(除了死去的SuperSu),因為早期的Ruri https://github.com/RikkaApps/Riru 已經不更新了。
image

大規模棄更事件

而且,由於一些眾所周知的令人氣憤而又無奈的原因,Lsposed團隊的多個專案也不再更新(歸檔了)。

也許有人不明白不再更新的意義是什麼。我說一個最淺顯的表現,這些專案將很有可能不能在較新的機型上使用,比如如今的Android15機型

可以說這個事件造成了非常壞的影響,禍不單行,小米很快更新瞭解鎖的條件,具體是什麼大家都清楚。

時間先後我記不得了,我只記得這兩件事發生的時間很近,不超過一年。

我知道有很多人會說,哪怕沒有這些開發者,也會有Root的實現。沒有SuperSu,也會出現UltraSu;沒有Ruri,也會有Zygisk。你看Zygisk Next不是出現了嗎。

那我確實沒法反對,根據客觀規律,有需求就有市場,上面這段話是對的。但是這種話是最不該對Lsposed團隊說的,因為Lsposed是被社群推動的,可以說近乎是浪漫的產物;同時期下EdXposed依然在被使用,他們完全可以不開發這個東西。

可以看到,EdXposed並沒有歸檔,只是不再更新了
image
為什麼不更新呢?因為顯而易見,別人的專案Lsposed更好,維護EdXposed沒有意義了。幾個EdXposed的維護者全跑去更新Lsposed了。

假如EdXposed還在維護,你會去用Lsposed嗎?

題外話

如果你細心觀察,你會發現,搞root框架和相關的環境的維護者,來回就那麼幾個。
如果你說搞這些專案是為了給自己鍍金。
人家招聘的問你會什麼,你說你參與開發了Magisk,我聽著都想笑。
所有手機廠商都是不鼓勵你root的,因為使用者的權利和廠商的權利往往站在對立面。
我開發一個軟體,如果我想讓他按照我預想中的執行,最好的辦法就是使用者什麼都幹不了,使用者的許可權越大我的風險就越高,我不讓解鎖了。維護的版本越多bug就越多,那我強制更新不就好了。(很多軟體的做法)

因此顯然,鼓搗這些東西去工作時沒什麼用的。而且說難聽點,專案維護很大程度上都是體力活,費時間而沒有什麼技術含量。

回到正題

我們再拉回時間線。現在magisk依然如火如荼,Lsp依然如日中天(因為Android15並未普及),這兩者的出現都是一統江湖的,沒什麼競爭對手。(在當時)
而現在,出現了KernelSu和Apatch這兩個競爭者,我們可以重新梳理一下當前使用者的需求。

Root

除了SuperSu,這幾款軟體都實現了Magisk模組

  1. SuperSu(不再更新)
  2. Magisk
    https://github.com/topjohnwu/Magisk
  3. KernelSu(作者是太極和虛擬框架的作者weishu)
    https://github.com/tiann/KernelSU
  4. Apatch
    https://github.com/bmax121/APatch

提供Zygote注入環境

現在Zygote注入實現只剩下Zygisk方式了,不出意外以後不會再有Ruri

  1. Magisk官方提供的Zygisk以及MagiskHide(已經過時)
  2. Ruri(EdXp時期,以及Lsp的前期)
    https://github.com/RikkaApps/Riru
    叫琉璃的人太多,猜不出來是誰,或許只是一個泛稱
  3. Zygisk Next(唯一倖存者)
    https://github.com/Dr-TSNG/ZygiskNext

隱藏Root(隱藏注入器)

我不太清楚Zygisk什麼時候出現的。
KernelSu和Apatch都實現了隱藏su(也就是Root),但是如果你使用了Zygisk(Zygote注入的實現),你還需要隱藏Zygisk。

  1. Zygisk環境下,使用MagiskHide(自帶,停止更新)
  2. Shamiko(MagiskHide的一種實現?停止更新)

Shamiko借用的依然是官方Magisk的配置排除列表,需要Zygisk環境,預設是黑名單模式,也就是對列表中的應用隱藏Root。
Shamiko應該是夏美子,街角魔族的主角。(沒人比我更懂二次元.jpg)
image

  1. MagiskHide模組?(我沒用過)
  2. 其他的,有很多,但我不太瞭解......

Xposed模組實現/管理器

除了早期的Xposed Installer,這些必須有Zygote注入環境

  1. Xposed Installer和Manager(過時)
  2. Edxposed(過時)
    https://github.com/ElderDrivers/EdXposed
  3. Lsposed(停止維護)
    https://github.com/LSPosed
  4. Lsposed Mod(下一代)
    https://github.com/mywalkb/LSPosed_mod

回到正題

雖然很簡單,但是我講了一大堆(而且很亂)。
相容性最強的自然是各個實現只實現它本該實現的功能。
但是我們先說說相容性最差的情況,假設某個zip直接包含了全部的環境(以上的全部需求),是不是很強很方便?但是,首先沒有人有這麼大的精力去整合所有專案,其次,如果整合在一起,你如何知道哪個部分出了問題?
我們再說相容性最強的方案,假設每個功能都以單獨模組出現,那其實也很糟糕,假設Magisk分成了多個部分,比如把Root管理和模組管理分離,再把排除應用列表分離。那麼你從前卡刷面具這一步,就會複雜成刷好幾個模組,安裝好幾個應用。
其次,假設你只實現了Root管理,我憑什麼用你Magisk?一個應用只有解決了某個需求才會有人去用,才有意義,假設許多應用都只幹同一件事,那麼想要獲得使用者只能靠宣發了。而開源應用和宣發基本上沾不上邊,因為宣發是要錢的。搞開源已經很費錢了(時間也是錢),哪來的錢搞宣發。

還有一個原因,Magisk本身也在積極地更新,假如某個模組使用了Magisk的新功能,自然會存在不相容Apatch和KernelSu。(而且Apatch之類的和Magisk的環境也不同,而之前的模組都是以Magisk環境為準的)
而Apatch和KernelSu如果花時間去相容Magisk,完全是不務正業,而且吃力不討好,因為舊的寫法通常比新的多,為了5%的模組去花50%的時間並不值得。

所以這個問題無解,除非Magisk模組功能被單獨實現,但是這就更不可能了,因為Magisk的核心功能就是模組,他是用模組來解決問題的,倒不如說Root才是順帶的。

原諒我長篇大論一大堆說了這麼些淺顯的道理。

相關文章