@Override public void handleInitPackageResources(InitPackageResourcesParam resparam){ if (!resparam.packageName.equals(PACKAGE_NAME)) return; //如果不是UI则跳过 //这里将自带的图标资源插入到systemui中,并获取到一个资源id XModuleResources modRes = XModuleResources.createInstance(MODULE_PATH, resparam.res); //创建一个插入资源的实例 ic_toast_bg_fest = resparam.res.addResource(modRes, R.drawable.ic_toast_bg_fest); ic_toast_bg = resparam.res.addResource(modRes, R.drawable.ic_toast_bg); }
@Override public void handleInitPackageResources(XC_InitPackageResources.InitPackageResourcesParam liparam) throws Throwable { if (liparam.packageName.equals(PACKAGE_SYSTEMUI)) { try { XModuleResources modRes = XModuleResources.createInstance(MODULE_PATH, liparam.res); IC_HIDE_ID = liparam.res.addResource(modRes, R.mipmap.ic_sysbar_hide); IC_HIDE_LAND_ID = liparam.res.addResource(modRes, R.mipmap.ic_sysbar_hide_land); STRING_NAV_HIDE_ID = liparam.res.addResource(modRes, R.string.navbar_menu_hide); } catch (Exception e) { log(TAG + e); } } }
@Override public void initZygote(StartupParam startupParam) throws Throwable { mStatusBarView = null; mSettingsHelper = new SettingsHelper(new XSharedPreferences(PackageNames.OURS, SettingsHelper.PREFS)); mResources = XModuleResources.createInstance(startupParam.modulePath, null); findAndHookMethod( Activity.class, "onWindowFocusChanged", boolean.class, new OnWindowFocusedHook(mSettingsHelper, mResources)); findAndHookMethod( Activity.class, "performResume", new ActivityOnResumeHook(mSettingsHelper, mResources)); if (Utils.hasActionBar()) new ActionBarHooks(mSettingsHelper); // TODO: Fix this // WindowManagerServiceHooks.doHook(null); LGHooks.doImeHook(); }
@Override public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable { if (lpparam.packageName.equals(Common.PACKAGE_NFC)) { modRes = XModuleResources.createInstance(MODULE_PATH, null); reloadSoundsToPlayList(); Class<?> NfcService = null; // F**k you LG mIsOemStupid = false; try { NfcService = findClass(Common.PACKAGE_NFC + ".LNfcService", lpparam.classLoader); mIsOemStupid = true; } catch (ClassNotFoundError e) { e.printStackTrace(); } if (NfcService == null) { try { NfcService = findClass(Common.PACKAGE_NFC + ".NfcService", lpparam.classLoader); } catch (ClassNotFoundError e) { // Shouldn't happen } } // Don't reload settings on every call, that can cause slowdowns. // This intent is fired from NFCLockScreenOffEnablerActivity when // any of the parameters change. XC_MethodHook initNfcServiceHook = new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { nfcServiceObject = param.thisObject; mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); mContext.registerReceiver( new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { XposedBridge.log(MY_PACKAGE_NAME + ": " + "Settings updated, reloading..."); AndroidAppHelper.reloadSharedPreferencesIfNeeded(prefs); // This may be faster than using prefs.getBoolean, since we use this a lot. mDebugMode = prefs.getBoolean(Common.PREF_DEBUG_MODE, true); reloadSoundsToPlayList(); } }, new IntentFilter(Common.SETTINGS_UPDATED_INTENT)); } }; boolean hookedSuccessfully = true; try { Constructor<?> NfcServiceConstructor = XposedHelpers.findConstructorBestMatch(NfcService, Application.class); XposedBridge.hookMethod(NfcServiceConstructor, initNfcServiceHook); } catch (NoSuchMethodError e) { hookedSuccessfully = false; } if (!hookedSuccessfully) { try { findAndHookMethod(NfcService, "onCreate", initNfcServiceHook); } catch (NoSuchMethodError e) { e.printStackTrace(); } } try { findAndHookMethod( NfcService, "initSoundPool", new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { mSoundPool = (SoundPool) XposedHelpers.getObjectField(param.thisObject, "mSoundPool"); synchronized (param.thisObject) { if (mSoundPool != null) { mTagLostSound = mSoundPool.load(modRes.openRawResourceFd(R.raw.tag_lost), 1); } } } }); } catch (NoSuchMethodError e) { e.printStackTrace(); } try { findAndHookMethod( NfcService, "playSound", int.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { int event = (Integer) param.args[0]; if ((event == SOUND_START && !mSoundsToPlayList.contains("sound_start")) || (event == SOUND_END && !mSoundsToPlayList.contains("sound_end")) || (event == SOUND_ERROR && !mSoundsToPlayList.contains("sound_error"))) { param.setResult(false); } } }); } catch (NoSuchMethodError e) { e.printStackTrace(); } XC_MethodHook checkScreenStateHook = new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { final String enableNfcWhen = prefs.getString(Common.PREF_ENABLE_NFC_WHEN, "locked_screen_on"); if (enableNfcWhen.equals("unlocked")) return; try { Boolean NeedScreenOnState = (Boolean) XposedHelpers.getAdditionalInstanceField( param.thisObject, "NeedScreenOnState"); if (NeedScreenOnState == null || NeedScreenOnState == false) return; param.setResult(SCREEN_STATE_ON_UNLOCKED); } catch (Exception e) { e.printStackTrace(); } } }; // Nfc module of some kinds of ROMs may call checkScreenState in applyRouting // and update mScreenState, so we have to hook checkScreenState and modify // the return value try { findAndHookMethod(NfcService, "checkScreenState", checkScreenStateHook); } catch (NoSuchMethodError e) { try { findAndHookMethod( Common.PACKAGE_NFC + ".NfcService", lpparam.classLoader, "checkScreenState", checkScreenStateHook); } catch (NoSuchMethodError e1) { e1.printStackTrace(); } } try { if (mIsOemStupid) { /* The subject seems to be have shown signs of intelligence here. * LG's implementation of NFC supports NFC while screen is off/locked. * This might be because of their weird NFC sending feature, or not. */ findAndHookMethod( NfcService, "applyRouting", boolean.class, new XC_MethodHook() { protected void beforeHookedMethod(MethodHookParam param) throws Throwable { final String enableNfcWhen = prefs.getString(Common.PREF_ENABLE_NFC_WHEN, "locked_screen_on"); if (enableNfcWhen.equals("unlocked")) { XposedHelpers.setIntField(param.thisObject, "POLLING_MODE", 0); } else if (enableNfcWhen.equals("locked_screen_on")) { XposedHelpers.setIntField(param.thisObject, "POLLING_MODE", 2); } else if (enableNfcWhen.equals("screen_off")) { XposedHelpers.setIntField(param.thisObject, "POLLING_MODE", 1); } }; }); } else { findAndHookMethod( NfcService, "applyRouting", boolean.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { final String enableNfcWhen = prefs.getString(Common.PREF_ENABLE_NFC_WHEN, "locked_screen_on"); if (enableNfcWhen.equals("unlocked")) return; try { final int currScreenState = (Integer) XposedHelpers.callMethod(param.thisObject, "checkScreenState"); // We also don't need to run if the screen is already on, or if the user // has chosen to enable NFC on the lockscreen only and the phone is not locked if ((currScreenState == SCREEN_STATE_ON_UNLOCKED) || (enableNfcWhen.equals("locked_screen_on") && currScreenState != SCREEN_STATE_ON_LOCKED)) { XposedHelpers.setAdditionalInstanceField( param.thisObject, "mOrigScreenState", -1); return; } // we are in applyRouting, set the flag NeedScreenOnState to true XposedHelpers.setAdditionalInstanceField( param.thisObject, "NeedScreenOnState", true); synchronized ( param.thisObject) { // Not sure if this is correct, but NfcService.java // insists on having accesses to the mScreenState // variable synchronized, so I'm doing the same here XposedHelpers.setAdditionalInstanceField( param.thisObject, "mOrigScreenState", XposedHelpers.getIntField(param.thisObject, "mScreenState")); XposedHelpers.setIntField( param.thisObject, "mScreenState", SCREEN_STATE_ON_UNLOCKED); } } catch (Exception e) { e.printStackTrace(); } } @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { try { final String enableNfcWhen = prefs.getString(Common.PREF_ENABLE_NFC_WHEN, "locked_screen_on"); if (enableNfcWhen.equals("unlocked")) return; // exit from applyRouting, set the flag NeedScreenOnState to false XposedHelpers.setAdditionalInstanceField( param.thisObject, "NeedScreenOnState", false); final int mOrigScreenState = (Integer) XposedHelpers.getAdditionalInstanceField( param.thisObject, "mOrigScreenState"); if (mOrigScreenState == -1) return; synchronized (param.thisObject) { // Restore original mScreenState value after applyRouting has run XposedHelpers.setIntField(param.thisObject, "mScreenState", mOrigScreenState); } } catch (Exception e) { e.printStackTrace(); } } }); } } catch (NoSuchMethodError e) { e.printStackTrace(); } try { findAndHookMethod( NfcService, "onRemoteEndpointDiscovered", Common.PACKAGE_NFC + ".DeviceHost$TagEndpoint", new NfcServiceOnRemoteEndpointDiscoveredHook()); } catch (ClassNotFoundError e) { e.printStackTrace(); } try { Class<?> PresenceCheckWatchDog = findClass( Common.PACKAGE_NFC + ".dhimpl.NativeNfcTag$PresenceCheckWatchdog", lpparam.classLoader); findAndHookMethod(PresenceCheckWatchDog, "run", new PresenceCheckWatchdogRunHook()); } catch (ClassNotFoundError e) { if (mDebugMode) XposedBridge.log("Not hooking class .dhimpl.NativeNfcTag$PresenceCheckWatchdog"); } try { Class<?> PresenceCheckWatchdog = findClass( Common.PACKAGE_NFC + ".nxp.NativeNfcTag$PresenceCheckWatchdog", lpparam.classLoader); findAndHookMethod(PresenceCheckWatchdog, "run", new PresenceCheckWatchdogRunHook()); } catch (ClassNotFoundError e) { if (mDebugMode) XposedBridge.log("Not hooking class .nxp.NativeNfcTag$PresenceCheckWatchdog"); } } if (lpparam.packageName.equals("android")) { final int currentapiVersion = android.os.Build.VERSION.SDK_INT; try { String className; if (currentapiVersion < android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { className = "com.android.internal.policy.impl.LockPatternKeyguardView"; } else { className = "com.android.internal.policy.impl.keyguard.KeyguardHostView"; } Class<?> ClassToHook = findClass(className, lpparam.classLoader); // public KeyguardHostView(Context context, AttributeSet attrs) // public LockPatternKeyguardView(Context context, KeyguardViewCallback callback, // KeyguardUpdateMonitor updateMonitor, LockPatternUtils lockPatternUtils, // KeyguardWindowController controller) // Class KeyguardHostView on 4.2+ has mCallback of type KeyguardSecurityCallback, // while 4.1- has mKeyguardScreenCallback of type KeyguardScreenCallback. // Both of which have a method called reportSuccessfulUnlockAttempt() that // should be the first step in unlocking the device. XposedBridge.hookAllConstructors( ClassToHook, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { String fieldName; if (currentapiVersion < android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { fieldName = "mKeyguardScreenCallback"; } else { fieldName = "mCallback"; } try { mKeyguardSecurityCallbackInstance = getObjectField(param.thisObject, fieldName); } catch (NoSuchFieldError e) { } Context context = (Context) param.args[0]; registerNfcUnlockReceivers(context); } }); } catch (ClassNotFoundError e) { } catch (NoSuchFieldError e) { } // The classes and field names were renamed and moved around between 4.1 and 4.2, // the bits we're interested in stayed the same though. try { String className; if (currentapiVersion < android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { className = "com.android.internal.policy.impl.KeyguardViewManager"; } else { className = "com.android.internal.policy.impl.keyguard.KeyguardViewManager"; } Class<?> KeyguardViewManager = findClass(className, lpparam.classLoader); XposedBridge.hookAllConstructors( KeyguardViewManager, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { try { String fieldName; if (currentapiVersion < android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { fieldName = "mCallback"; } else { fieldName = "mViewMediatorCallback"; } mViewMediatorCallback = XposedHelpers.getObjectField(param.thisObject, fieldName); } catch (NoSuchFieldError e) { e.printStackTrace(); } } }); } catch (ClassNotFoundError e) { XposedBridge.log( "Class not found: " + e.getMessage().toString() + " NFC Unlocking won't work"); } } // for HTC if (lpparam.packageName.equals("com.htc.lockscreen") && !mBroadcastReceiverRegistered) { Class<?> ClassToHook = findClass("com.htc.lockscreen.HtcKeyguardHostViewImpl", lpparam.classLoader); XposedBridge.hookAllConstructors( ClassToHook, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { try { mKeyguardSecurityCallbackInstance = getObjectField(param.thisObject, "mSecurityCallback"); } catch (NoSuchFieldError e) { } Context context = (Context) param.args[0]; registerNfcUnlockReceivers(context); } }); } }