@@ -586,40 +586,249 @@ void touchInputStop() {
586586
587587} // namespace
588588
589- TouchHelper::TouchHelper () = default;
589+ TouchHelper::TouchHelper ()
590+ : backend_(TouchBackend::UINPUT )
591+ , initialized_(false )
592+ , shizukuBridgeAvailable_(false )
593+ , javaVm_(nullptr )
594+ , activityClassGlobal_(nullptr )
595+ , shizukuMoveMethod_(nullptr )
596+ , shizukuUpMethod_(nullptr ) {}
590597
591598TouchHelper::~TouchHelper () {
599+ if (javaVm_ && activityClassGlobal_) {
600+ JNIEnv* env = nullptr ;
601+ if (javaVm_->GetEnv (reinterpret_cast <void **>(&env), JNI_VERSION_1_6 ) == JNI_OK && env) {
602+ env->DeleteGlobalRef (activityClassGlobal_);
603+ }
604+ }
592605 shutdown ();
593606}
594607
608+ void TouchHelper::setBackend (TouchBackend backend) {
609+ if (backend_ == backend) {
610+ return ;
611+ }
612+ releaseActiveTouch ();
613+ shutdownUinput ();
614+ initialized_ = false ;
615+ backend_ = backend;
616+ }
617+
618+ void TouchHelper::setJniBridge (JavaVM* vm, JNIEnv* env, jobject activityInstance) {
619+ javaVm_ = vm;
620+ if (!env || !activityInstance) {
621+ return ;
622+ }
623+
624+ if (activityClassGlobal_) {
625+ env->DeleteGlobalRef (activityClassGlobal_);
626+ activityClassGlobal_ = nullptr ;
627+ }
628+
629+ jclass localClass = env->GetObjectClass (activityInstance);
630+ if (!localClass) {
631+ return ;
632+ }
633+ activityClassGlobal_ = static_cast <jclass>(env->NewGlobalRef (localClass));
634+ env->DeleteLocalRef (localClass);
635+
636+ shizukuMoveMethod_ = nullptr ;
637+ shizukuUpMethod_ = nullptr ;
638+ }
639+
640+ void TouchHelper::setShizukuBridgeAvailable (bool available) {
641+ shizukuBridgeAvailable_ = available;
642+ if (!available && backend_ == TouchBackend::SHIZUKU ) {
643+ shutdown ();
644+ }
645+ }
646+
595647bool TouchHelper::init () {
596- if (g_touchStart ) {
648+ if (initialized_ ) {
597649 return true ;
598650 }
599651
652+ if (backend_ == TouchBackend::SHIZUKU ) {
653+ initialized_ = initShizuku ();
654+ return initialized_;
655+ }
656+
657+ initialized_ = initUinput ();
658+ return initialized_;
659+ }
660+
661+ bool TouchHelper::initUinput () {
662+ if (g_touchStart) {
663+ return true ;
664+ }
600665 touchInputStart ();
601666 return g_touchStart;
602667}
603668
669+ bool TouchHelper::initShizuku () {
670+ return shizukuBridgeAvailable_;
671+ }
672+
673+ void TouchHelper::releaseActiveTouch () {
674+ if (!initialized_) {
675+ return ;
676+ }
677+
678+ if (backend_ == TouchBackend::SHIZUKU ) {
679+ callShizukuUp ();
680+ return ;
681+ }
682+
683+ sendTouchUp ();
684+ }
685+
604686void TouchHelper::setScreenSize (int width, int height) {
605687 updateRes (width, height);
606688}
607689
608690void TouchHelper::touchDown (int slot, float x, float y) {
609691 (void )slot;
692+ if (!initialized_ && !init ()) {
693+ return ;
694+ }
695+
696+ if (backend_ == TouchBackend::SHIZUKU ) {
697+ if (!callShizukuMove (x, y, true )) {
698+ initialized_ = false ;
699+ }
700+ return ;
701+ }
610702 sendTouchMove (static_cast <int >(x), static_cast <int >(y));
611703}
612704
613705void TouchHelper::touchMove (int slot, float x, float y) {
614706 (void )slot;
707+ if (!initialized_ && !init ()) {
708+ return ;
709+ }
710+
711+ if (backend_ == TouchBackend::SHIZUKU ) {
712+ if (!callShizukuMove (x, y, false )) {
713+ initialized_ = false ;
714+ }
715+ return ;
716+ }
615717 sendTouchMove (static_cast <int >(x), static_cast <int >(y));
616718}
617719
618720void TouchHelper::touchUp (int slot) {
619721 (void )slot;
722+ if (!initialized_) {
723+ return ;
724+ }
725+
726+ if (backend_ == TouchBackend::SHIZUKU ) {
727+ if (!callShizukuUp ()) {
728+ initialized_ = false ;
729+ }
730+ return ;
731+ }
620732 sendTouchUp ();
621733}
622734
623735void TouchHelper::shutdown () {
736+ releaseActiveTouch ();
737+ shutdownUinput ();
738+ initialized_ = false ;
739+ }
740+
741+ bool TouchHelper::isInitialized () const {
742+ return initialized_;
743+ }
744+
745+ void TouchHelper::shutdownUinput () {
624746 touchInputStop ();
625747}
748+
749+ bool TouchHelper::ensureJniMethods (JNIEnv* env) {
750+ if (!env || !activityClassGlobal_) {
751+ return false ;
752+ }
753+
754+ if (!shizukuMoveMethod_) {
755+ shizukuMoveMethod_ = env->GetStaticMethodID (
756+ activityClassGlobal_,
757+ " nativeInjectShizukuAimMove" ,
758+ " (FFZ)Z"
759+ );
760+ }
761+ if (!shizukuUpMethod_) {
762+ shizukuUpMethod_ = env->GetStaticMethodID (
763+ activityClassGlobal_,
764+ " nativeInjectShizukuAimUp" ,
765+ " ()Z"
766+ );
767+ }
768+
769+ return shizukuMoveMethod_ && shizukuUpMethod_;
770+ }
771+
772+ bool TouchHelper::callShizukuMove (float x, float y, bool isFirst) {
773+ if (!javaVm_ || !shizukuBridgeAvailable_) {
774+ return false ;
775+ }
776+
777+ JNIEnv* env = nullptr ;
778+ bool attached = false ;
779+ if (javaVm_->GetEnv (reinterpret_cast <void **>(&env), JNI_VERSION_1_6 ) != JNI_OK ) {
780+ if (javaVm_->AttachCurrentThread (&env, nullptr ) != JNI_OK ) {
781+ return false ;
782+ }
783+ attached = true ;
784+ }
785+
786+ bool ok = false ;
787+ if (ensureJniMethods (env)) {
788+ const jboolean result = env->CallStaticBooleanMethod (
789+ activityClassGlobal_,
790+ shizukuMoveMethod_,
791+ static_cast <jfloat>(x),
792+ static_cast <jfloat>(y),
793+ static_cast <jboolean>(isFirst)
794+ );
795+ ok = (result == JNI_TRUE ) && !env->ExceptionCheck ();
796+ if (env->ExceptionCheck ()) {
797+ env->ExceptionClear ();
798+ }
799+ }
800+
801+ if (attached) {
802+ javaVm_->DetachCurrentThread ();
803+ }
804+ return ok;
805+ }
806+
807+ bool TouchHelper::callShizukuUp () {
808+ if (!javaVm_ || !shizukuBridgeAvailable_) {
809+ return false ;
810+ }
811+
812+ JNIEnv* env = nullptr ;
813+ bool attached = false ;
814+ if (javaVm_->GetEnv (reinterpret_cast <void **>(&env), JNI_VERSION_1_6 ) != JNI_OK ) {
815+ if (javaVm_->AttachCurrentThread (&env, nullptr ) != JNI_OK ) {
816+ return false ;
817+ }
818+ attached = true ;
819+ }
820+
821+ bool ok = false ;
822+ if (ensureJniMethods (env)) {
823+ const jboolean result = env->CallStaticBooleanMethod (activityClassGlobal_, shizukuUpMethod_);
824+ ok = (result == JNI_TRUE ) && !env->ExceptionCheck ();
825+ if (env->ExceptionCheck ()) {
826+ env->ExceptionClear ();
827+ }
828+ }
829+
830+ if (attached) {
831+ javaVm_->DetachCurrentThread ();
832+ }
833+ return ok;
834+ }
0 commit comments