commit 9a5b577b77a6a87efcd8e6e218693af6faed17ce Author: Codex AuthorDate: Thu Nov 5 18:12:47 2026 +0800 Commit: Codex CommitDate: Thu Nov 5 18:12:47 2026 +0800 Skip ineligible review preparation and reuse candidate identity diff --git a/native/src/com/android/commands/monkey/ape/jev/JevSemanticReview.java b/native/src/com/android/commands/monkey/ape/jev/JevSemanticReview.java index d4a6100..0ae9707 100644 --- a/native/src/com/android/commands/monkey/ape/jev/JevSemanticReview.java +++ b/native/src/com/android/commands/monkey/ape/jev/JevSemanticReview.java @@ -153,15 +153,18 @@ public final class JevSemanticReview implements AutoCloseable { public void prepare(State state,GUITree tree) { prepare(state,tree,currentStep); } public void prepare(State state,GUITree tree,long step) {prepare(state,tree,step,null);} void prepare(State state,GUITree tree,long step,JevRuntime.Validator validator) { + long prepareStart=JevReviewProfile.start(); // This flag describes this invocation's construction error, not a prior round. localFailure=false;localEvidenceNanos=0;providerWaitNanos=0; final long absolute=System.nanoTime()+TimeUnit.MILLISECONDS.toNanos(timeoutMs); try (JevDeadline budget=JevDeadline.enter(absolute)) { + long lockStart=JevReviewProfile.start(); try { if(!reviewLock.tryLock(Math.max(0,absolute-System.nanoTime()),TimeUnit.NANOSECONDS)) { healthy=false;selectionBlocked=true;return; } } catch(InterruptedException e) {Thread.currentThread().interrupt();healthy=false;selectionBlocked=true;return;} + finally {JevReviewProfile.end("review_lock_wait",lockStart);} try { currentStep=step;nativeValidator=validator; if(reviewId!=null)registry.semanticEvent("SEMANTIC_REVIEW_STARTED",step,state==null?null:state.getGraphId(),null, @@ -174,33 +177,42 @@ public final class JevSemanticReview implements AutoCloseable { healthy=false;selectionBlocked=true; try {failOpen(state,"DEADLINE");}catch(JevDeadline.Expired ignored) { /* audit lock busy: do not wait again */ } } finally {nativeValidator=null;reviewLock.unlock();} - } + } finally {JevReviewProfile.end("prepare_total",prepareStart);} } private void prepareLocked(State state,GUITree tree,long deadline) { selectionBlocked=false;localFailure=false; Page previous=preparedPage;preparedPage=null; if(previous!=null)contextInvalidated(previous,"prepare_reentered"); - if(state==null||tree==null||tree.getCurrentState()!=state)return; + if(state==null||tree==null||tree.getCurrentState()!=state){JevReviewProfile.add("return_invalid_context",0,1);return;} JevDeadline.check(); if(!synchronous)poll(); + // A fresh round requires a >=3-member action. Smaller groups can only + // supply already accepted pending work. Check that necessary condition + // before rendering identities or walking exact-execution history. + long eligibilityStart=JevReviewProfile.start(); + boolean workPossible=hasReviewWork(state,tree); + JevReviewProfile.end("review_eligibility",eligibilityStart); + if(!workPossible){JevReviewProfile.add("return_no_review_work",0,1);return;} long scanStart=JevReviewProfile.start(); Map lightweight=collectCandidates(state,tree); JevReviewProfile.end("candidate_enumeration",scanStart); - if(lightweight.isEmpty())return; + if(lightweight.isEmpty()){JevReviewProfile.add("return_no_candidates",0,1);return;} long selectStart=JevReviewProfile.start(); Set roundKeys=selectRoundKeys(state,tree,lightweight); JevReviewProfile.end("round_selection",selectStart); - if(roundKeys.isEmpty())return; + if(roundKeys.isEmpty()){JevReviewProfile.add("return_no_round",0,1);return;} Map reusable=new LinkedHashMap(); for(Candidate candidate:lightweight.values())if(roundKeys.contains(candidate.key)&&candidate.staged!=null && "PROBE".equals(candidate.staged.decision.outcome))reusable.put(candidate.key,candidate); if(!reusable.isEmpty()) { preparedPage=new Page(state.getGraphId()+"|staged",new JSONObject(),reusable); preparedState=state;preparedTree=tree; + JevReviewProfile.add("return_staged_probe",0,1); return; } Page page;long evidenceStart=System.nanoTime(); - try {page=roundPage(state,tree,roundKeys,lightweight);}finally{localEvidenceNanos+=System.nanoTime()-evidenceStart;} + long pairStart=JevReviewProfile.start(); + try {page=roundPage(state,tree,roundKeys,lightweight);}finally{localEvidenceNanos+=System.nanoTime()-evidenceStart;JevReviewProfile.end("round_page",pairStart);} preparedPage=page;preparedState=state;preparedTree=tree; if(page==null||page.candidates.isEmpty()||page.payload.optJSONArray("pairs").length()==0)return; // A staged PROMOTE is an executable piece of work. Do not spend this @@ -327,6 +339,16 @@ public final class JevSemanticReview implements AutoCloseable { } } } + private boolean hasReviewWork(State state,GUITree tree) { + for(ModelAction action:state.getActions()) { + JevDeadline.check(); + if(!action.requireTarget()||action.isBack()||!action.isValid()||!action.isEnabled())continue; + GUITreeNode[] nodes=action.getResolvedNodes(); + if(nodes!=null&&nodes.length>=MIN_CONCRETE_ACTIONS&&action.getResolvedGUITree()==tree)return true; + } + // Do not apply the fresh-round size threshold to persistent Probes. + return registry.reviewLedger().hasPendingProbe(contract,state); + } private Map collectCandidates(State state,GUITree tree) { Map candidates=new LinkedHashMap();Set ambiguous=new HashSet();int number=0; for(ModelAction action:state.getActions()) { @@ -336,16 +358,19 @@ public final class JevSemanticReview implements AutoCloseable { if(nodes==null||nodes.length==0||action.getResolvedGUITree()!=tree)continue; for(GUITreeNode node:nodes) { JevDeadline.check();if(registry.hasExactExecution(state,action,tree,node))continue; - String id="c"+(++number),identity=key(action,node); + ConcreteActionIdentity concrete=ConcreteActionIdentity.of(action.getType().name(),node); + String id="c"+(++number),identity=scope(action)+"|"+concrete.toString(); if(ambiguous.contains(identity))continue; if(candidates.containsKey(identity)){candidates.remove(identity);ambiguous.add(identity);} - else {Candidate c=new Candidate(action,node,identity,id);c.concreteIdentity=ConcreteActionIdentity.of(action.getType().name(),node);candidates.put(identity,c);} + else {Candidate c=new Candidate(action,node,identity,id);c.concreteIdentity=concrete;candidates.put(identity,c);} } } return candidates; } private JevReviewLedger.Staged staged(Candidate c,String gui,State state){ - return registry.reviewLedger().staged(contract,state,c.action,identity(c),gui,modelVersion,registry.executionRevision(state,c.action),registry.confirmationCount()); + long start=JevReviewProfile.start(); + try {return registry.reviewLedger().staged(contract,state,c.action,identity(c),gui,modelVersion,registry.executionRevision(state,c.action),registry.confirmationCount());} + finally {JevReviewProfile.end("staged_lookup",start);} } private boolean executable(Candidate c,State state,GUITree tree){ if(c.staged==null||!"PROBE".equals(c.staged.decision.outcome)||!c.node.isEnabled() @@ -359,7 +384,8 @@ public final class JevSemanticReview implements AutoCloseable { finally {action.resolveAt((int)currentStep,throttle,tree,previous,action.getResolvedNodes());action.setResolvedGUITreeAction(previousAction);} } private Set selectRoundKeys(State state,GUITree tree,Map all) { - String gui=JevEvidence.guiIdentity(tree);List reusable=new ArrayList(),fresh=new ArrayList(); + long guiStart=JevReviewProfile.start();String gui=JevEvidence.guiIdentity(tree);JevReviewProfile.end("round_gui_identity",guiStart); + List reusable=new ArrayList(),fresh=new ArrayList(); for(Candidate c:all.values()){ c.staged=staged(c,gui,state); if(c.staged!=null){