Beispiel #1
0
    @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);
            }
          });
    }
  }