├── .classpath ├── .cproject ├── .gitignore ├── .project ├── .settings ├── org.eclipse.cdt.codan.core.prefs └── org.eclipse.jdt.core.prefs ├── AndroidManifest.xml ├── assets └── .gitignore ├── jni ├── Android.mk ├── events.h ├── input_recorder.c ├── input_replayer.c ├── jni_log.h ├── recorder.h ├── replayer.h └── uinput.h ├── libs ├── android-support-v4.jar └── armeabi │ ├── libinputrecorder.so │ └── libinputreplayer.so ├── lint.xml ├── obj └── local │ └── armeabi │ ├── libinputrecorder.so │ └── libinputreplayer.so ├── proguard-project.txt ├── project.properties ├── res ├── drawable-hdpi │ └── ic_launcher.png ├── drawable-ldpi │ └── .gitignore ├── drawable-mdpi │ └── ic_launcher.png ├── drawable-xhdpi │ └── ic_launcher.png ├── layout │ ├── activity_main.xml │ └── repeat_layout.xml └── values │ ├── dimens.xml │ └── strings.xml └── src └── com └── dll ├── touchrepeater ├── InputRecorder.java ├── InputReplayer.java ├── MainActivity.java ├── RepeatLayout.java ├── RepeatService.java └── RootPermission.java └── util └── FilePathUtil.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.cproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | 15 | # Gradle files 16 | .gradle/ 17 | build/ 18 | 19 | # Local configuration file (sdk path, etc) 20 | local.properties 21 | 22 | # Proguard folder generated by Eclipse 23 | proguard/ 24 | 25 | # Log Files 26 | *.log 27 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | TouchRepeater 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | ?children? 14 | ?children?=?name?=entry\\\\\\\|\\\|?name?=entry\\\\\\\|\\\|\|?name?=outputEntries\|| 15 | 16 | 17 | ?name? 18 | 19 | 20 | 21 | org.eclipse.cdt.make.core.append_environment 22 | true 23 | 24 | 25 | org.eclipse.cdt.make.core.buildArguments 26 | 27 | 28 | 29 | org.eclipse.cdt.make.core.buildCommand 30 | ndk-build 31 | 32 | 33 | org.eclipse.cdt.make.core.cleanBuildTarget 34 | clean 35 | 36 | 37 | org.eclipse.cdt.make.core.contents 38 | org.eclipse.cdt.make.core.activeConfigSettings 39 | 40 | 41 | org.eclipse.cdt.make.core.enableAutoBuild 42 | false 43 | 44 | 45 | org.eclipse.cdt.make.core.enableCleanBuild 46 | true 47 | 48 | 49 | org.eclipse.cdt.make.core.enableFullBuild 50 | true 51 | 52 | 53 | org.eclipse.cdt.make.core.stopOnError 54 | true 55 | 56 | 57 | org.eclipse.cdt.make.core.useDefaultBuildCmd 58 | false 59 | 60 | 61 | 62 | 63 | com.android.ide.eclipse.adt.ResourceManagerBuilder 64 | 65 | 66 | 67 | 68 | com.android.ide.eclipse.adt.PreCompilerBuilder 69 | 70 | 71 | 72 | 73 | org.eclipse.jdt.core.javabuilder 74 | 75 | 76 | 77 | 78 | com.android.ide.eclipse.adt.ApkBuilder 79 | 80 | 81 | 82 | 83 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 84 | full,incremental, 85 | 86 | 87 | 88 | 89 | 90 | com.android.ide.eclipse.adt.AndroidNature 91 | org.eclipse.jdt.core.javanature 92 | org.eclipse.cdt.core.cnature 93 | org.eclipse.cdt.core.ccnature 94 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 95 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 96 | 97 | 98 | -------------------------------------------------------------------------------- /.settings/org.eclipse.cdt.codan.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.cdt.codan.checkers.errnoreturn=Warning 3 | org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false} 4 | org.eclipse.cdt.codan.checkers.errreturnvalue=Error 5 | org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 6 | org.eclipse.cdt.codan.checkers.noreturn=Error 7 | org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false} 8 | org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error 9 | org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 10 | org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error 11 | org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 12 | org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning 13 | org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 14 | org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error 15 | org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 16 | org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning 17 | org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false} 18 | org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning 19 | org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},unknown\=>false,exceptions\=>()} 20 | org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error 21 | org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 22 | org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning 23 | org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},skip\=>true} 24 | org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error 25 | org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 26 | org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error 27 | org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 28 | org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error 29 | org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 30 | org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error 31 | org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 32 | org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error 33 | org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 34 | org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error 35 | org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 36 | org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error 37 | org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 38 | org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info 39 | org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},pattern\=>"^[a-z]",macro\=>true,exceptions\=>()} 40 | org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning 41 | org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 42 | org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error 43 | org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 44 | org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error 45 | org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 46 | org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error 47 | org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 48 | org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning 49 | org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 50 | org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning 51 | org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 52 | org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning 53 | org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>()} 54 | org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning 55 | org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},paramNot\=>false} 56 | org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning 57 | org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},else\=>false,afterelse\=>false} 58 | org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error 59 | org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 60 | org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning 61 | org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true} 62 | org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning 63 | org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true} 64 | org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning 65 | org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>("@(\#)","$Id")} 66 | org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error 67 | org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} 68 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 3 | org.eclipse.jdt.core.compiler.compliance=1.6 4 | org.eclipse.jdt.core.compiler.source=1.6 5 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /assets/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaobinlzy/touchRepeater_Android/f40a7652867888e83b4691867a04388a04407d3d/assets/.gitignore -------------------------------------------------------------------------------- /jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | LOCAL_LDLIBS := -llog 6 | LOCAL_MODULE := inputrecorder 7 | LOCAL_SRC_FILES := input_recorder.c 8 | LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES) 9 | include $(BUILD_SHARED_LIBRARY) 10 | 11 | include $(CLEAR_VARS) 12 | LOCAL_LDLIBS := -llog 13 | LOCAL_MODULE := inputreplayer 14 | LOCAL_SRC_FILES := input_replayer.c 15 | LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES) 16 | include $(BUILD_SHARED_LIBRARY) -------------------------------------------------------------------------------- /jni/events.h: -------------------------------------------------------------------------------- 1 | /* 2 | * events.h 3 | * 4 | * Created on: 2014年6月13日 5 | * Author: DLL 6 | */ 7 | 8 | #ifndef EVENTS_H_ 9 | #define EVENTS_H_ 10 | 11 | const char *event_prefix = "/dev/input/"; 12 | const char *event_devices[] = { "event0", "event1", "event2", "event3", "event4", "event5", "event6", "event7" }; 13 | #define NUM_DEVICES (sizeof(event_devices) / sizeof(char *)) 14 | #endif /* EVENTS_H_ */ 15 | -------------------------------------------------------------------------------- /jni/input_recorder.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "jni_log.h" 4 | #include "recorder.h" 5 | 6 | JNIEXPORT void JNICALL Java_com_dll_touchrepeater_InputRecorder_nativeStop(JNIEnv *env, 7 | jobject thiz, jlong recorderPointer) 8 | { 9 | struct recorder* recorder = (void *) (long) recorderPointer; 10 | stop(recorder); 11 | } 12 | 13 | JNIEXPORT jlong JNICALL Java_com_dll_touchrepeater_InputRecorder_nativeInit(JNIEnv *env, 14 | jobject thiz, jstring recordFilePath) 15 | { 16 | const char* filePath = (*env)->GetStringUTFChars(env, recordFilePath, 0); 17 | struct recorder* recorder = init(filePath); 18 | 19 | (*env)->ReleaseStringUTFChars(env, recordFilePath, filePath); 20 | return (jlong) (long) recorder; 21 | } 22 | 23 | JNIEXPORT jint JNICALL Java_com_dll_touchrepeater_InputRecorder_nativeRecord(JNIEnv *env, 24 | jobject thiz, jlong recorderPointer) 25 | { 26 | struct recorder* recorder = (void *) (long) recorderPointer; 27 | int recordResult = record(recorder); 28 | destroy(recorder); 29 | return recordResult; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /jni/input_replayer.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "jni_log.h" 4 | #include "replayer.h" 5 | 6 | #ifndef _Included_com_dll_touchrepeater_InputReplayer 7 | #define _Included_com_dll_touchrepeater_InputReplayer 8 | 9 | JNIEXPORT jlong JNICALL Java_com_dll_touchrepeater_InputReplayer_nativeInit 10 | (JNIEnv *env, jobject thiz, jstring replayFilePath) 11 | { 12 | const char *filePath = (*env)->GetStringUTFChars(env, replayFilePath, 0); 13 | struct replayer* replayer = init(filePath); 14 | (*env)->ReleaseStringUTFChars(env, replayFilePath, filePath); 15 | return (jlong)(long) replayer; 16 | } 17 | 18 | JNIEXPORT jint JNICALL Java_com_dll_touchrepeater_InputReplayer_nativeReplay 19 | (JNIEnv *env, jobject thiz, jlong replayerPointer, jint repeatTimes) 20 | { 21 | struct replayer* replayer = (void *)(long) replayerPointer; 22 | int replayResult = replay(replayer, repeatTimes); 23 | destroy(replayer); 24 | return replayResult; 25 | } 26 | 27 | JNIEXPORT void JNICALL Java_com_dll_touchrepeater_InputReplayer_nativeStop 28 | (JNIEnv *env, jobject thiz, jlong replayerPointer) 29 | { 30 | struct replayer* replayer = (void *)(long) replayerPointer; 31 | stop(replayer); 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /jni/jni_log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * jni_log.h 3 | * 4 | * Created on: 2014年6月13日 5 | * Author: DLL 6 | */ 7 | 8 | #include 9 | 10 | #ifndef JNI_LOG_H_ 11 | #define JNI_LOG_H_ 12 | 13 | 14 | 15 | #define TAG "JNI_LOG" 16 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , TAG, __VA_ARGS__) 17 | #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__) 18 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) 19 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__) 20 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) 21 | 22 | #endif /* JNI_LOG_H_ */ 23 | -------------------------------------------------------------------------------- /jni/recorder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * recorder.h 3 | * 4 | * Created on: 2014年6月13日 5 | * Author: DLL 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "jni_log.h" 16 | #include "events.h" 17 | 18 | #ifndef RECORDER_H_ 19 | #define RECORDER_H_ 20 | 21 | struct recorder 22 | { 23 | int is_recording; 24 | int out_fd; 25 | struct pollfd *in_fds; 26 | }; 27 | 28 | void destroy(struct recorder* recorder); 29 | 30 | struct recorder* init(const char* filePath) 31 | { 32 | char buffer[256]; 33 | int fd, i; 34 | struct recorder *recorder = malloc(sizeof(struct recorder)); 35 | memset(recorder, 0, sizeof(recorder)); 36 | struct pollfd *in_fds = malloc(NUM_DEVICES * sizeof(struct pollfd)); 37 | recorder->in_fds = in_fds; 38 | 39 | recorder->out_fd = open(filePath, O_WRONLY | O_CREAT | O_TRUNC); 40 | if (recorder->out_fd < 0) 41 | { 42 | LOGD("Couldn't open output file: %s", filePath); 43 | destroy(recorder); 44 | return 0; 45 | } 46 | for (i = 0; i < NUM_DEVICES; i++) 47 | { 48 | sprintf(buffer, "%s%s", event_prefix, event_devices[i]); 49 | recorder->in_fds[i].events = POLLIN; 50 | recorder->in_fds[i].fd = open(buffer, O_RDONLY | O_NDELAY); 51 | if (recorder->in_fds[i].fd < 0) 52 | { 53 | LOGD("Couldn't open input device %s", buffer); 54 | destroy(recorder); 55 | return 0; 56 | } 57 | } 58 | recorder->is_recording = 1; 59 | LOGD("recorder init ok"); 60 | return recorder; 61 | } 62 | 63 | void stop(struct recorder * recorder) 64 | { 65 | recorder->is_recording = 0; 66 | } 67 | 68 | int record(struct recorder * recorder) 69 | { 70 | int i, num_read; 71 | struct input_event event; 72 | while (recorder->is_recording) 73 | { 74 | if (poll(recorder->in_fds, NUM_DEVICES, -1) < 0) 75 | { 76 | LOGD("poll error"); 77 | return 1; 78 | } 79 | if (recorder->is_recording) 80 | { 81 | for (i = 0; i < NUM_DEVICES; i++) 82 | { 83 | if (recorder->in_fds[i].revents & POLLIN) 84 | { 85 | num_read = read(recorder->in_fds[i].fd, &event, sizeof(event)); 86 | if (num_read != sizeof(event)) 87 | { 88 | LOGD("read error"); 89 | return 2; 90 | } 91 | if ((write(recorder->out_fd, &i, sizeof(i)) != sizeof(i) 92 | || write(recorder->out_fd, &event, sizeof(event)) != sizeof(event))) 93 | { 94 | LOGD("Write error\n"); 95 | return 3; 96 | } 97 | LOGD("event: %d %08x %08x %08x", i, event.type, event.code, event.value); 98 | } 99 | } 100 | } 101 | else 102 | { 103 | break; 104 | } 105 | } 106 | return 0; 107 | } 108 | 109 | void closeFiles(struct recorder* recorder) 110 | { 111 | int result = 0, i; 112 | for (i = 0; i < NUM_DEVICES; i++) 113 | { 114 | if (recorder->in_fds[i].fd > 0) 115 | { 116 | result += close(recorder->in_fds[i].fd); 117 | } 118 | } 119 | if (recorder->out_fd > 0) 120 | { 121 | result += close(recorder->out_fd); 122 | } 123 | LOGD("close file: %d", result); 124 | } 125 | 126 | void destroy(struct recorder* recorder) 127 | { 128 | closeFiles(recorder); 129 | free(recorder->in_fds); 130 | free(recorder); 131 | } 132 | 133 | #endif /* RECORDER_H_ */ 134 | -------------------------------------------------------------------------------- /jni/replayer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * replayer.h 3 | * 4 | * Created on: 2014年6月13日 5 | * Author: DLL 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "events.h" 18 | #include "uinput.h" 19 | 20 | #ifndef REPLAYER_H_ 21 | #define REPLAYER_H_ 22 | 23 | struct replayer 24 | { 25 | int is_replaying; 26 | int in_fd; 27 | int *out_fds; 28 | int num_events; 29 | char file_path[256]; 30 | }; 31 | 32 | void destroy(struct replayer* replayer); 33 | 34 | struct replayer* init(const char* filePath) 35 | { 36 | struct stat statinfo; 37 | 38 | if (stat(filePath, &statinfo) == -1) 39 | { 40 | LOGD("Couldn't stat input\n"); 41 | return 0; 42 | } 43 | 44 | struct replayer *replayer = malloc(sizeof(struct replayer)); 45 | memset(replayer, 0, sizeof(struct replayer)); 46 | int *out_fds = malloc(NUM_DEVICES * sizeof(int)); 47 | replayer->out_fds = out_fds; 48 | strcpy(replayer->file_path, filePath); 49 | char buffer[256]; 50 | int i; 51 | 52 | for (i = 0; i < NUM_DEVICES; i++) 53 | { 54 | sprintf(buffer, "%s%s", event_prefix, event_devices[i]); 55 | replayer->out_fds[i] = open(buffer, O_WRONLY | O_NDELAY); 56 | if (replayer->out_fds[i] < 0) 57 | { 58 | LOGD("Couldn't open output device\n"); 59 | destroy(replayer); 60 | return 0; 61 | } 62 | } 63 | replayer->num_events = statinfo.st_size / (sizeof(struct input_event) + sizeof(int)); 64 | if ((replayer->in_fd = open(filePath, O_RDONLY)) < 0) 65 | { 66 | LOGD("Couldn't open input\n"); 67 | destroy(replayer); 68 | return 0; 69 | } 70 | 71 | ioctl(replayer->out_fds[3], UI_SET_EVBIT, EV_KEY); 72 | ioctl(replayer->out_fds[3], UI_SET_EVBIT, EV_REP); 73 | ioctl(replayer->out_fds[1], UI_SET_EVBIT, EV_ABS); 74 | 75 | replayer->is_replaying = 1; 76 | LOGD("replayer init ok"); 77 | return replayer; 78 | } 79 | 80 | int replay(struct replayer* replayer, int repeatTimes) 81 | { 82 | int time; 83 | for (time = 0; time < repeatTimes && replayer->is_replaying; time++) 84 | { 85 | sleep(1); 86 | struct timeval tdiff; 87 | struct input_event event; 88 | int i, outputdev; 89 | timerclear(&tdiff); 90 | LOGD("num events: %d", replayer->num_events); 91 | for (i = 0; i < replayer->num_events && replayer->is_replaying; i++) 92 | { 93 | struct timeval now, tevent, tsleep; 94 | 95 | if (read(replayer->in_fd, &outputdev, sizeof(outputdev)) != sizeof(outputdev) 96 | || read(replayer->in_fd, &event, sizeof(event)) != sizeof(event)) 97 | { 98 | LOGD("Input read error\n"); 99 | return 1; 100 | } 101 | 102 | gettimeofday(&now, NULL); 103 | if (!timerisset(&tdiff)) 104 | { 105 | timersub(&now, &event.time, &tdiff); 106 | } 107 | 108 | timeradd(&event.time, &tdiff, &tevent); 109 | timersub(&tevent, &now, &tsleep); 110 | if (tsleep.tv_sec > 0 || tsleep.tv_usec > 100) 111 | select(0, NULL, NULL, NULL, &tsleep); 112 | 113 | event.time = tevent; 114 | if (write(replayer->out_fds[outputdev], &event, sizeof(event)) != sizeof(event)) 115 | { 116 | LOGD("Output write error\n"); 117 | return 2; 118 | } 119 | } 120 | replayer->in_fd = close(replayer->in_fd); 121 | LOGD("open file: %s", replayer->file_path); 122 | if ((replayer->in_fd = open(replayer->file_path, O_RDONLY)) < 0) { 123 | LOGD("Couldn't open input\n"); 124 | return 3; 125 | } 126 | 127 | } 128 | return 0; 129 | } 130 | 131 | void closeFiles(struct replayer* replayer) 132 | { 133 | int result = 0, i; 134 | for (i = 0; i < NUM_DEVICES; i++) 135 | { 136 | if (replayer->out_fds[i] > 0) 137 | { 138 | result += close(replayer->out_fds[i]); 139 | } 140 | } 141 | if (replayer->in_fd > 0) 142 | { 143 | result += close(replayer->in_fd); 144 | } 145 | LOGD("close file: %d", result); 146 | } 147 | 148 | void destroy(struct replayer* replayer) 149 | { 150 | closeFiles(replayer); 151 | free(replayer->out_fds); 152 | free(replayer); 153 | LOGD("replayer destroy"); 154 | } 155 | 156 | void stop(struct replayer* replayer) 157 | { 158 | replayer->is_replaying = 0; 159 | } 160 | #endif /* REPLAYER_H_ */ 161 | -------------------------------------------------------------------------------- /jni/uinput.h: -------------------------------------------------------------------------------- 1 | /* Android munges Linux headers to avoid copyright issues, but doesn't munge linux/uinput.h, 2 | * so constants reproduced here. 3 | */ 4 | 5 | #ifndef __UINPUT__ 6 | #define __UINPUT__ 7 | 8 | 9 | #define UI_SET_EVBIT 0x40045564 10 | #define UI_SET_KEYBIT 0x40045565 11 | #define UI_SET_RELBIT 0x40045566 12 | #define UI_SET_ABSBIT 0x40045567 13 | 14 | #define UINPUT_MAX_NAME_SIZE 80 15 | 16 | struct uinput_id { 17 | uint16_t bustype; 18 | uint16_t vendor; 19 | uint16_t product; 20 | uint16_t version; 21 | }; 22 | 23 | struct uinput_dev { 24 | char name[UINPUT_MAX_NAME_SIZE]; 25 | struct uinput_id id; 26 | int ff_effects_max; 27 | int absmax[ABS_MAX + 1]; 28 | int absmin[ABS_MAX + 1]; 29 | int absfuzz[ABS_MAX + 1]; 30 | int absflat[ABS_MAX + 1]; 31 | }; 32 | 33 | struct uinput_event { 34 | struct timeval time; 35 | uint16_t type; 36 | uint16_t code; 37 | int32_t value; 38 | }; 39 | 40 | 41 | #endif /* __UINPUT__ */ 42 | -------------------------------------------------------------------------------- /libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaobinlzy/touchRepeater_Android/f40a7652867888e83b4691867a04388a04407d3d/libs/android-support-v4.jar -------------------------------------------------------------------------------- /libs/armeabi/libinputrecorder.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaobinlzy/touchRepeater_Android/f40a7652867888e83b4691867a04388a04407d3d/libs/armeabi/libinputrecorder.so -------------------------------------------------------------------------------- /libs/armeabi/libinputreplayer.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaobinlzy/touchRepeater_Android/f40a7652867888e83b4691867a04388a04407d3d/libs/armeabi/libinputreplayer.so -------------------------------------------------------------------------------- /lint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /obj/local/armeabi/libinputrecorder.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaobinlzy/touchRepeater_Android/f40a7652867888e83b4691867a04388a04407d3d/obj/local/armeabi/libinputrecorder.so -------------------------------------------------------------------------------- /obj/local/armeabi/libinputreplayer.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaobinlzy/touchRepeater_Android/f40a7652867888e83b4691867a04388a04407d3d/obj/local/armeabi/libinputreplayer.so -------------------------------------------------------------------------------- /proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-19 15 | -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaobinlzy/touchRepeater_Android/f40a7652867888e83b4691867a04388a04407d3d/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-ldpi/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaobinlzy/touchRepeater_Android/f40a7652867888e83b4691867a04388a04407d3d/res/drawable-ldpi/.gitignore -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaobinlzy/touchRepeater_Android/f40a7652867888e83b4691867a04388a04407d3d/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaobinlzy/touchRepeater_Android/f40a7652867888e83b4691867a04388a04407d3d/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /res/layout/repeat_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 |