Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
1802b02
feat: property guided algorithm
majuzi123 Aug 26, 2025
d6e2189
feat: property guided algorithm
majuzi123 Aug 26, 2025
797aa29
Merge remote-tracking branch 'origin/main' into testV2
majuzi123 Nov 30, 2025
d590800
feat: property guided algorithm v2.0
majuzi123 Nov 30, 2025
c4d9a2a
feat: property guided algorithm v3.0
majuzi123 Dec 4, 2025
ee7cfbe
update: dump xml to native when adding preconditions
majuzi123 Dec 5, 2025
37e1ce6
feat: add XPathTester class and test XML for XPath evaluation
majuzi123 Dec 9, 2025
01e116d
feat: enhance guidance mechanism with new hyperparameters and action …
majuzi123 Dec 9, 2025
466692a
feat: implement guided algorithm v3 —— action feedback processing and…
majuzi123 Feb 4, 2026
dccef7e
feat: enhance precondition history tracking and template generation i…
majuzi123 Feb 4, 2026
bc3ea56
feat: update guidance path template structure and enhance guided acti…
majuzi123 Feb 5, 2026
e885a1f
feat: standardize template sequence length and reliability initializa…
majuzi123 Feb 6, 2026
547ca5b
Merge remote-tracking branch 'origin/main' into guide_algorithmV3
majuzi123 Feb 6, 2026
241969f
merge main into guide_algorithmV3
majuzi123 Feb 6, 2026
0a8d97c
feat: separate precondition pages storage to companion .precond file
majuzi123 Feb 6, 2026
f57557f
chore: downgrade Gradle and Android plugin versions for compatibility
majuzi123 Feb 11, 2026
36b70df
fix: resolve IncompatibleClassChangeError on older Android devices ca…
majuzi123 Feb 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added archive/monkeyq.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ allprojects {

tasks.register('clean', Delete) {
delete rootProject.buildDir
}
}
19 changes: 19 additions & 0 deletions build_c++.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

cd "native"

rm -r CMakeFiles/
cmake -DCMAKE_TOOLCHAIN_FILE="D:\Android\Sdk\ndk\25.2.9519653\build\cmake\android.toolchain.cmake" -DANDROID_ABI=armeabi-v7a -DCMAKE_BUILD_TYPE=Release
nmake
rm -r CMakeFiles/

cmake -DCMAKE_TOOLCHAIN_FILE="D:\Android\Sdk\ndk\25.2.9519653\build\cmake\android.toolchain.cmake" -DANDROID_ABI=arm64-v8a -DCMAKE_BUILD_TYPE=Release
nmake
rm -r CMakeFiles/

cmake -DCMAKE_TOOLCHAIN_FILE="D:\Android\Sdk\ndk\25.2.9519653\build\cmake\android.toolchain.cmake" -DANDROID_ABI=x86 -DCMAKE_BUILD_TYPE=Release
nmake
rm -r CMakeFiles/

cmake -DCMAKE_TOOLCHAIN_FILE="D:\Android\Sdk\ndk\25.2.9519653\build\cmake\android.toolchain.cmake" -DANDROID_ABI=x86_64 -DCMAKE_BUILD_TYPE=Release
nmake
rm -r CMakeFiles/
Binary file modified libs/arm64-v8a/libfastbot_native.so
Binary file not shown.
Binary file modified libs/armeabi-v7a/libfastbot_native.so
Binary file not shown.
Binary file modified libs/x86/libfastbot_native.so
Binary file not shown.
Binary file modified libs/x86_64/libfastbot_native.so
Binary file not shown.
2 changes: 1 addition & 1 deletion monkey/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,4 @@ task makeThirdPartJar(type: Jar) {
destinationDirectory = file("$buildDir/libs")
}

tasks.assemble.finalizedBy makeThirdPartJar
tasks.assemble.finalizedBy makeThirdPartJar
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ public Element getRootElement(Document tree) {
String cur_package;
if (node.getNodeType() == Node.ELEMENT_NODE) {
cur_package = ((Element) node).getAttribute("package");
if (!"com.android.systemui".equals(cur_package) && !cur_package.contains("inputmethod") && !"android".equals(cur_package)) {
if (!"com.android.systemui".equals(cur_package) && !cur_package.contains("inputmethod") && !"android".equals(cur_package) && !cur_package.contains("gesture") && !cur_package.contains("com.hihonor.android.FloatTasks")) {
if (mVerbose > 3){
Logger.println("[MonkeySourceApeU2] RootElement:"+cur_package);
}
Expand Down Expand Up @@ -826,7 +826,7 @@ protected void generateEvents() {

generateEventsForAction(modelAction);

// check if could select next fuzz action from full fuzz-able action options.
// check if could select next fuzz action from full fuzzing list or simplified fuzzing list.
switch (type) {
case RESTART:
case CLEAN_RESTART:
Expand Down Expand Up @@ -1587,4 +1587,46 @@ public void tearDown() {
printCoverage();
}

/**
* Ensure current stringOfGuiTree is available and send it to native layer as precondition.
* This centralizes the native call so ProxyServer can simply delegate here and reuse
* the exact same pageDesc formatting as used by getAction(...).
*/
public boolean sendCurrentPageAsPrecondition() {
Logger.println("[MonkeySourceApeU2] sendCurrentPageAsPrecondition: enter");
try {
// Always refresh hierarchy first (do not use cached stringOfGuiTree at the beginning)
Logger.println("[MonkeySourceApeU2] forcing dumpHierarchy() to refresh latest GUI tree");
try {
this.dumpHierarchy();
Logger.println("[MonkeySourceApeU2] dumpHierarchy completed, stringOfGuiTree length=" + (this.stringOfGuiTree == null ? 0 : this.stringOfGuiTree.length()));
} catch (Exception ex) {
Logger.errorPrintln("[MonkeySourceApeU2] dumpHierarchy failed before sending precondition: " + ex.getMessage());
}

if (this.stringOfGuiTree != null && !this.stringOfGuiTree.isEmpty()) {
Logger.println("[MonkeySourceApeU2] calling native addCurrentPageAsPreconditionSync...");
boolean ok = AiClient.addCurrentPageAsPreconditionSyncOk(this.stringOfGuiTree);
if (ok) {
Logger.println("[MonkeySourceApeU2] Sent current page as precondition to native");
Logger.println("[MonkeySourceApeU2] Precondition XML length: " + this.stringOfGuiTree.length());
Logger.println("[MonkeySourceApeU2] Precondition XML start ---");
Logger.println(this.stringOfGuiTree);
Logger.println("[MonkeySourceApeU2] Precondition XML end ---");
return true;
} else {
Logger.errorPrintln("[MonkeySourceApeU2] Native failed to process precondition");
return false;
}
} else {
Logger.errorPrintln("[MonkeySourceApeU2] stringOfGuiTree is empty after forced dump, abort sending precondition");
return false;
}
} catch (Throwable t) {
Logger.errorPrintln("[MonkeySourceApeU2] sendCurrentPageAsPrecondition failed: " + t.getMessage());
t.printStackTrace();
return false;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import org.json.JSONException;
import org.json.JSONObject;


public class ProxyServer extends NanoHTTPD {

private final OkHttpClient client;
Expand Down Expand Up @@ -112,6 +111,10 @@ public Response serve(IHTTPSession session) {
);
}

if (session.getMethod() == Method.GET && uri.equals("/propertyFirstSatisfied")) {
return handlePropertyFirstSatisfied();
}

// parse the request body data
Map<String, String> data = new HashMap<>();
String requestBody = "";
Expand Down Expand Up @@ -255,6 +258,9 @@ public Response serve(IHTTPSession session) {
return forward(uri, method, requestBody);
}




public File getDeviceOutputDir(){
return outputDir;
}
Expand Down Expand Up @@ -562,4 +568,50 @@ public void recordMonkeyStep(Action action){
}
recordLog(action, screenshot_file);
}
}

private Response handlePropertyFirstSatisfied() {
// Use a synchronous call with timeout: call sendCurrentPageAsPrecondition and wait for up to TIMEOUT_MS.
final int TIMEOUT_MS = 8000; // 8 seconds timeout, tunable
if (this.eventSource == null) {
Logger.errorPrintln("[ProxyServer] eventSource is null, cannot send precondition");
return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, "text/plain", "{\"status\":\"error\",\"message\":\"eventSource not available\"}");
}

java.util.concurrent.ExecutorService ex = java.util.concurrent.Executors.newSingleThreadExecutor();
java.util.concurrent.Future<Boolean> f = ex.submit(new java.util.concurrent.Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
try {
return ProxyServer.this.eventSource.sendCurrentPageAsPrecondition();
} catch (Throwable t) {
Logger.errorPrintln("[ProxyServer] sendCurrentPageAsPrecondition threw: " + t.getMessage());
return false;
}
}
});

boolean success = false;
try {
success = f.get(TIMEOUT_MS, java.util.concurrent.TimeUnit.MILLISECONDS);
} catch (java.util.concurrent.TimeoutException te) {
f.cancel(true);
Logger.errorPrintln("[ProxyServer] sendCurrentPageAsPrecondition timed out after " + TIMEOUT_MS + "ms");
ex.shutdownNow();
return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, "text/plain", "{\"status\":\"error\",\"message\":\"timeout\"}");
} catch (Exception e) {
Logger.errorPrintln("[ProxyServer] Exception when waiting for sendCurrentPageAsPrecondition: " + e.getMessage());
ex.shutdownNow();
return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, "text/plain", "{\"status\":\"error\",\"message\":\"exception\"}");
} finally {
ex.shutdownNow();
}

if (success) {
Logger.println("[ProxyServer] sendCurrentPageAsPrecondition succeeded");
return newFixedLengthResponse(Response.Status.OK, "text/plain", "{\"status\":\"ok\"}");
} else {
Logger.errorPrintln("[ProxyServer] sendCurrentPageAsPrecondition reported failure");
return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, "text/plain", "{\"status\":\"error\",\"message\":\"native failed\"}");
}
}
}
11 changes: 11 additions & 0 deletions monkey/src/main/java/com/bytedance/fastbot/AiClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,15 @@ public Operate b1bhkadf(String activity, String pageDesc) {
return Operate.fromJson(operateStr);
}

public static native void addCurrentPageAsPrecondition(String xml);

// Native sync method: returns 0 on success, non-zero on error
private static native int addCurrentPageAsPreconditionSync(String xml);

// Java wrapper that returns boolean for success
public static boolean addCurrentPageAsPreconditionSyncOk(String xml) {
int status = addCurrentPageAsPreconditionSync(xml);
return status == 0;
}

}
Binary file modified monkeyq.jar
Binary file not shown.
Loading