2121import com .sevtinge .hyperceiler .common .log .XposedLog ;
2222import com .sevtinge .hyperceiler .common .utils .api .ProjectApi ;
2323import com .sevtinge .hyperceiler .libhook .utils .api .ContextUtils ;
24+ import com .sevtinge .hyperceiler .libhook .utils .api .ThreadPoolManager ;
2425import com .sevtinge .hyperceiler .libhook .utils .hookapi .dexkit .DexKit ;
2526import com .sevtinge .hyperceiler .libhook .utils .hookapi .tool .EzxHelpUtils ;
2627import com .sevtinge .hyperceiler .libhook .utils .hookapi .tool .ResourcesTool ;
2728
2829import java .io .PrintWriter ;
2930import java .io .StringWriter ;
31+ import java .util .ArrayList ;
32+ import java .util .List ;
3033import java .util .Objects ;
34+ import java .util .concurrent .ExecutionException ;
35+ import java .util .concurrent .Future ;
3136import java .util .function .BooleanSupplier ;
3237
3338import io .github .libxposed .api .XposedInterface ;
@@ -54,6 +59,10 @@ public abstract class BaseLoad {
5459 private static volatile String sCurrentHookTag = "BaseLoad" ;
5560 public static ResourcesTool mResHook ;
5661 private boolean mDexKitSessionPrepared = false ;
62+ private final List <BaseHook > mPendingDexKitHooks = new ArrayList <>();
63+
64+ private record DexKitInitResult (BaseHook hook , boolean shouldInit , Throwable error ) {
65+ }
5766
5867 /**
5968 * 初始化 Xposed 运行时入口。
@@ -121,6 +130,7 @@ public void onLoad(PackageReadyParam lpparam) {
121130 sCurrentHookTag = this .getClass ().getSimpleName ();
122131 mResHook = ResourcesTool .getInstance (getXposed ().getModuleApplicationInfo ().sourceDir );
123132 mDexKitSessionPrepared = false ;
133+ mPendingDexKitHooks .clear ();
124134 }
125135
126136 loadModuleResources ();
@@ -141,6 +151,7 @@ public void onLoad(SystemServerStartingParam lpparam) {
141151 sCurrentHookTag = this .getClass ().getSimpleName ();
142152 mResHook = ResourcesTool .getInstance (getXposed ().getModuleApplicationInfo ().sourceDir );
143153 mDexKitSessionPrepared = false ;
154+ mPendingDexKitHooks .clear ();
144155 }
145156
146157 loadModuleResources ();
@@ -167,7 +178,11 @@ private void executeHook() {
167178 try {
168179 onPackageLoaded ();
169180 } finally {
170- closeDexKitSession ();
181+ try {
182+ flushPendingDexKitHooks ();
183+ } finally {
184+ closeDexKitSession ();
185+ }
171186 }
172187 }
173188
@@ -187,40 +202,106 @@ private void closeDexKitSession() {
187202 }
188203
189204 protected void initHook (BaseHook hook ) {
190- initHook (hook , () -> true );
205+ try {
206+ initHookInternal (hook , true );
207+ } catch (Throwable t ) {
208+ logHookFailure (hook , t );
209+ }
191210 }
192211
193212 protected void initHook (BaseHook hook , boolean isInit ) {
194- initHook (hook , () -> isInit );
213+ try {
214+ initHookInternal (hook , isInit );
215+ } catch (Throwable t ) {
216+ logHookFailure (hook , t );
217+ }
195218 }
196219
197220 protected void initHook (BaseHook hook , BooleanSupplier condition ) {
198221 if (hook == null ) return ;
199222
200223 try {
201- if (condition .getAsBoolean ()) {
202- if (hook .useDexKit () && !isSystemServer ()) {
203- prepareDexKitSession (hook .TAG );
204- hook .setDexKitInitInProgress (true );
205- try {
206- if (!hook .initDexKit ()) {
207- XposedLog .w (hook .TAG , getPackageName (), "Skip hook because initDexKit returned false" );
208- return ;
209- }
210- } catch (Throwable t ) {
211- XposedLog .e (hook .TAG , getPackageName (), "Skip hook because initDexKit failed" , t );
212- return ;
213- } finally {
214- hook .setDexKitInitInProgress (false );
215- }
216- }
217- hook .init ();
218- XposedLog .i (hook .TAG , getPackageName (), "Hook Success" );
224+ if (!mPendingDexKitHooks .isEmpty ()) {
225+ flushPendingDexKitHooks ();
226+ }
227+ initHookInternal (hook , condition .getAsBoolean ());
228+ } catch (Throwable t ) {
229+ logHookFailure (hook , t );
230+ }
231+ }
232+
233+ private void initHookInternal (BaseHook hook , boolean shouldInit ) {
234+ if (hook == null || !shouldInit ) return ;
235+ if (hook .useDexKit () && !isSystemServer ()) {
236+ prepareDexKitSession (hook .TAG );
237+ mPendingDexKitHooks .add (hook );
238+ return ;
239+ }
240+ flushPendingDexKitHooks ();
241+ runHookInit (hook );
242+ }
243+
244+ private void flushPendingDexKitHooks () {
245+ if (mPendingDexKitHooks .isEmpty ()) return ;
246+
247+ List <BaseHook > pendingHooks = new ArrayList <>(mPendingDexKitHooks );
248+ mPendingDexKitHooks .clear ();
249+
250+ List <Future <DexKitInitResult >> futures = new ArrayList <>(pendingHooks .size ());
251+ for (BaseHook hook : pendingHooks ) {
252+ futures .add (ThreadPoolManager .getInstance ().submit (() -> runDexKitInit (hook )));
253+ }
254+
255+ List <DexKitInitResult > results = new ArrayList <>(pendingHooks .size ());
256+ for (int i = 0 ; i < futures .size (); i ++) {
257+ BaseHook hook = pendingHooks .get (i );
258+ try {
259+ results .add (futures .get (i ).get ());
260+ } catch (InterruptedException e ) {
261+ Thread .currentThread ().interrupt ();
262+ results .add (new DexKitInitResult (hook , false , e ));
263+ } catch (ExecutionException e ) {
264+ Throwable cause = e .getCause () != null ? e .getCause () : e ;
265+ results .add (new DexKitInitResult (hook , false , cause ));
266+ }
267+ }
268+
269+ for (DexKitInitResult result : results ) {
270+ if (result .error != null ) {
271+ XposedLog .e (result .hook .TAG , getPackageName (), "Skip hook because initDexKit failed" , result .error );
272+ continue ;
273+ }
274+ if (!result .shouldInit ) {
275+ XposedLog .w (result .hook .TAG , getPackageName (), "Skip hook because initDexKit returned false" );
276+ continue ;
277+ }
278+ try {
279+ runHookInit (result .hook );
280+ } catch (Throwable t ) {
281+ logHookFailure (result .hook , t );
219282 }
283+ }
284+ }
285+
286+ private DexKitInitResult runDexKitInit (BaseHook hook ) {
287+ hook .setDexKitInitInProgress (true );
288+ try {
289+ return new DexKitInitResult (hook , hook .initDexKit (), null );
220290 } catch (Throwable t ) {
221- StringWriter sw = new StringWriter ( );
222- t . printStackTrace ( new PrintWriter ( sw ));
223- XposedLog . e ( hook .TAG , getPackageName (), "Hook Failed: " + sw );
291+ return new DexKitInitResult ( hook , false , t );
292+ } finally {
293+ hook .setDexKitInitInProgress ( false );
224294 }
225295 }
296+
297+ private void runHookInit (BaseHook hook ) {
298+ hook .init ();
299+ XposedLog .i (hook .TAG , getPackageName (), "Hook Success" );
300+ }
301+
302+ private void logHookFailure (BaseHook hook , Throwable t ) {
303+ StringWriter sw = new StringWriter ();
304+ t .printStackTrace (new PrintWriter (sw ));
305+ XposedLog .e (hook .TAG , getPackageName (), "Hook Failed: " + sw );
306+ }
226307}
0 commit comments