[{"path":"native/src/com/android/commands/monkey/ape/jev/JevRegion.java","sha256":"b5a6fa3a445d94ff17e6b35b2bfb328d311bf791afc8e419ceedd2c969ff1a03","excerpts":[{"start":42,"end":104,"text":"42:     static final class Link {\n43:         final int source,target,concrete;\n44:         Link(int s,int t,int c){source=s;target=t;concrete=c;}\n45:     }\n46:     static final class Concrete {\n47:         final int id,source;final Set<Integer> targets;final boolean eligible;\n48:         Concrete(int i,int s,Set<Integer> t,boolean e){id=i;source=s;targets=Collections.unmodifiableSet(new HashSet<Integer>(t));eligible=e;}\n49:     }\n50:     static final class Snapshot {\n51:         final long abstraction,topology,concretes,facts;final int current;final String tree;\n52:         final List<Fact> states;final List<Link> links;final Set<Integer> roots;final List<Concrete> entries;\n53:         Snapshot(long a,long t,long c,long f,int cur,String tr,List<Fact> s,List<Link> l,Set<Integer> r,List<Concrete> e){\n54:             abstraction=a;topology=t;concretes=c;facts=f;current=cur;tree=tr;\n55:             states=Collections.unmodifiableList(new ArrayList<Fact>(s));links=Collections.unmodifiableList(new ArrayList<Link>(l));\n56:             roots=Collections.unmodifiableSet(new HashSet<Integer>(r));entries=Collections.unmodifiableList(new ArrayList<Concrete>(e));\n57:         }\n58:     }\n59:     static final class Result {\n60:         final Snapshot input;final Set<Integer> blocked,isolated,members;final List<Set<Integer>> regions;final String reason;final long nanos,dominatorNanos,summaryNanos,reachabilityNanos;\n61:         Result(Snapshot s,Set<Integer>b,Set<Integer>i,Set<Integer>m,List<Set<Integer>> regions,String r,long n,long d,long a,long reach){\n62:             input=s;blocked=Collections.unmodifiableSet(b);isolated=Collections.unmodifiableSet(i);members=Collections.unmodifiableSet(m);\n63:             List<Set<Integer>> copy=new ArrayList<Set<Integer>>();for(Set<Integer> region:regions)copy.add(Collections.unmodifiableSet(new HashSet<Integer>(region)));\n64:             this.regions=Collections.unmodifiableList(copy);reason=r;nanos=n;dominatorNanos=d;summaryNanos=a;reachabilityNanos=reach;\n65:         }\n66:     }\n67:     /** Tree reuse depends only on confirmed State connections and real roots, never strength. */\n68:     static final class Calculator {\n69:         long abstraction=-1,topology=-1;BitSet[] dominators;BitSet reachable;\n70:         int[] parents;List<List<Integer>> children;List<Integer> order;\n71:         void prepare(Snapshot s) {\n72:             int n=s.states.size();\n73:             if(abstraction!=s.abstraction || topology!=s.topology) {\n74:                 reachable=reach(s,s.roots,Collections.<Integer>emptySet());dominators=new BitSet[n];\n75:                 for(int i=0;i<n;i++){dominators[i]=new BitSet(n);if(reachable.get(i)){dominators[i].or(reachable);if(s.roots.contains(i)){dominators[i].clear();dominators[i].set(i);}}}\n76:                 List<List<Integer>> predecessors=new ArrayList<List<Integer>>();for(int i=0;i<n;i++)predecessors.add(new ArrayList<Integer>());\n77:                 for(Link l:s.links)if(reachable.get(l.source))predecessors.get(l.target).add(l.source);\n78:                 boolean changed;\n79:                 do {changed=false;for(int v=0;v<n;v++)if(reachable.get(v) && !s.roots.contains(v)) {\n80:                     checkInterrupted();BitSet d=(BitSet)reachable.clone();\n81:                     for(int p:predecessors.get(v))d.and(dominators[p]);\n82:                     d.set(v);if(!d.equals(dominators[v])){dominators[v]=d;changed=true;}\n83:                 }}while(changed);\n84:                 parents=new int[n];Arrays.fill(parents,-1);children=new ArrayList<List<Integer>>();order=new ArrayList<Integer>();\n85:                 for(int i=0;i<n;i++)children.add(new ArrayList<Integer>());\n86:                 for(int v=0;v<n;v++)if(reachable.get(v)) {\n87:                     checkInterrupted();int depth=-1;\n88:                     for(int d=dominators[v].nextSetBit(0);d>=0;d=dominators[v].nextSetBit(d+1))if(d!=v && dominators[d].cardinality()>depth){parents[v]=d;depth=dominators[d].cardinality();}\n89:                     if(parents[v]>=0)children.get(parents[v]).add(v);\n90:                 }\n91:                 for(int v=0;v<n;v++)if(reachable.get(v) && parents[v]<0)order.add(v);\n92:                 for(int i=0;i<order.size();i++)order.addAll(children.get(order.get(i)));\n93:                 abstraction=s.abstraction;topology=s.topology;\n94:             }\n95:         }\n96:         /** All non-entry dominator subtrees, independent of exploration facts. */\n97:         List<JevRegionLocator.Region> structure(Snapshot s) {\n98:             prepare(s);List<JevRegionLocator.Region> regions=new ArrayList<JevRegionLocator.Region>();\n99:             for(int d:order)if(!s.roots.contains(d)) {\n100:                 Set<Integer> members=new TreeSet<Integer>();ArrayDeque<Integer> queue=new ArrayDeque<Integer>();queue.add(d);\n101:                 while(!queue.isEmpty()){checkInterrupted();int v=queue.remove();members.add(v);queue.addAll(children.get(v));}\n102:                 regions.add(new JevRegionLocator.Region(d,members));\n103:             }\n104:             return regions;"},{"start":493,"end":517,"text":"493:     private void transitionNow(GUITreeTransition transition,String transitionId,boolean confirmed,String executionContextId,org.json.JSONObject sourceContext) {\n494:         if(!transitionIds.add(transitionId))return;\n495:         State source=transition.getSource().getCurrentState(),target=transition.getTarget().getCurrentState();int from=id(source),to=id(target);\n496:         GUITreeAction historical=transition.getAction();GUITreeNode node=historical.getGUITreeNode();\n497:         ModelAction action=locator==null?historical.getModelAction():shadowAction(transition);\n498:         GUITreeAction concrete=locator==null?historical:new GUITreeAction(transition.getSource(),node,action);\n499:         String name=node==null?\"<lifecycle>\":observedFullName(node);\n500:         Map<String,Bucket> group=byAction.get(action);if(group==null){group=new HashMap<String,Bucket>();byAction.put(action,group);}\n501:         Bucket bucket=group.get(name);if(bucket==null){bucket=new Bucket(nextConcreteId++,action,concrete);bucket.abstraction=abstraction;bucket.historicalAnchor=historical;buckets.put(bucket.id,bucket);group.put(name,bucket);concretes++;dirty=true;\n502:             if(locator!=null && action!=historical.getModelAction())locator.rebound(step,abstraction,shadowDiagnostic(bucket,transition));}\n503:         if(node!=null && observedNode(bucket.anchor,transition.getSource(),action)!=node)bucket.ambiguous=true;\n504:         if(implementations.add(from+\":\"+to+\":\"+bucket.id)){links.add(new Link(from,to,bucket.id));topology++;dirty=true;}\n505:         if(bucket.targets.add(to)){concretes++;dirty=true;}\n506:         if(confirmed) {\n507:             bucket.executions++;\n508:             bucket.confirmedTargets.add(transition.getTarget());\n509:             org.json.JSONArray labels=JevEvidence.resultLabels(transition.getTarget().getRootNode());\n510:             boolean sameGui=JevEvidence.guiIdentity(transition.getSource()).equals(JevEvidence.guiIdentity(transition.getTarget()));\n511:             String key=new org.json.JSONArray().put(target.getActivity()).put(labels).put(source==target).put(sameGui).toString();\n512:             bucket.confirmedPatterns.put(transitionId,key);\n513:             org.json.JSONObject outcome=bucket.outcomes.get(key);\n514:             if(outcome==null){outcome=JevRegistry.fields(\"target_activity\",JevEvidence.boundedText(target.getActivity()),\"result_labels\",labels,\"count\",0,\n515:                 \"self_loop\",source==target,\"activity_unchanged\",Objects.equals(source.getActivity(),target.getActivity()),\"gui_unchanged\",sameGui);bucket.outcomes.put(key,outcome);}\n516:             try{outcome.put(\"count\",outcome.getInt(\"count\")+1);}catch(org.json.JSONException impossible){throw new IllegalStateException(impossible);}\n517:         }"},{"start":599,"end":613,"text":"599:         try{if(locator!=null)shadowModel=model;safePointNow(model,state,tree,timestamp);}\n600:         catch(RuntimeException error){\n601:             if(locator==null)throw error;\n602:             shadowInvalid=error instanceof SnapshotInvalid?(SnapshotInvalid)error:new SnapshotInvalid(\"shadow_snapshot_exception\",JevRegistry.merge(shadowDiagnostic(null,null),JevRegistry.fields(\"exception\",error.getClass().getName(),\"message\",String.valueOf(error.getMessage()))));\n603:             if(locator.needsSnapshot())locator.snapshotInvalid(timestamp,abstraction,shadowInvalid.detail);\n604:         }\n605:         finally{timing.record(\"region_safe_point\",System.nanoTime()-started);}\n606:     }\n607:     private void safePointNow(Model model,State state,GUITree tree,long timestamp) {\n608:         step=timestamp;current=state;currentTree=tree;utgStateCount=model.getGraph().getStates().size();id(state);for(State root:model.getGraph().getEntryStates())root(root);touch(state);\n609:         recordMembershipVersion(model);\n610:         if(locator==null && !warmupStarted){warmupStarted=true;next=System.nanoTime()+warmup;events.emit(\"REGION_WARMUP_STARTED\",step,abstraction,state.getGraphId(),null,JevRegistry.fields(\"warmup_ms\",TimeUnit.NANOSECONDS.toMillis(warmup)));}\n611:         for(State touchedState:touched){Integer id=ids.get(touchedState);if(id==null)continue;Fact fact=runtime.explorationFact(touchedState);\n612:             if(!fact.equals(stateFacts.get(id))){stateFacts.set(id,fact);facts++;dirty=true;}}\n613:         touched.clear();"}]},{"path":"native/src/com/android/commands/monkey/ape/jev/JevRegionMatcher.java","sha256":"d25f67210f0836ccc971eb04f0c456a32ed5e299f81357722e45c16c97539315","excerpts":[{"start":1,"end":35,"text":"1: package com.android.commands.monkey.ape.jev;\n2: \n3: import com.android.commands.monkey.ape.model.ModelAction;\n4: import com.android.commands.monkey.ape.naming.NameManager;\n5: import com.android.commands.monkey.ape.tree.GUITree;\n6: import com.android.commands.monkey.ape.tree.GUITreeAction;\n7: import com.android.commands.monkey.ape.tree.GUITreeNode;\n8: \n9: /** Read-only classification shared by the production gate, KEEP cache and shadow. */\n10: final class JevRegionMatcher {\n11:     static final class Match {\n12:         final boolean source,action;\n13:         final GUITreeNode concrete;\n14:         final String reason;\n15:         Match(boolean source,boolean action,GUITreeNode concrete,String reason) {\n16:             this.source=source;this.action=action;this.concrete=concrete;this.reason=reason;\n17:         }\n18:         boolean exact(GUITreeNode node){return concrete!=null && concrete==node;}\n19:     }\n20:     static Match match(GUITreeAction anchor,GUITree tree,ModelAction action) {\n21:         if(anchor==null || tree==null || anchor.getGUITree().getCurrentState()!=tree.getCurrentState())\n22:             return new Match(false,false,null,\"source_state_mismatch\");\n23:         if(action==null || anchor.getModelAction()!=action)\n24:             return new Match(true,false,null,\"model_action_mismatch\");\n25:         GUITreeNode node=NameManager.withoutInterning(new java.util.function.Supplier<GUITreeNode>() {\n26:             public GUITreeNode get(){return JevRegistry.correspondingNode(anchor,tree,action);}\n27:         });\n28:         return new Match(true,true,node,node==null?\"concrete_absent_or_ambiguous\":\"exact\");\n29:     }\n30:     private JevRegionMatcher() { }\n31: }"}]},{"path":"native/src/com/android/commands/monkey/ape/jev/JevRegionLocator.java","sha256":"9231e3d2c5f8c04d3dd0b07b92a224094fb7767ef7e2425636bb43cf77e7a8d8","excerpts":[{"start":24,"end":33,"text":"24:     static long minutes(){return bounded(\"ape.jev.region_warmup_minutes\",10,0,Long.MAX_VALUE/TimeUnit.MINUTES.toNanos(1));}\n25:     static long windowSeconds(){return bounded(\"ape.jev.region_recent_window_seconds\",120,1,Long.MAX_VALUE/TimeUnit.SECONDS.toNanos(1));}\n26:     static int minimumRecent(){return (int)bounded(\"ape.jev.region_min_recent_visits\",3,1,Integer.MAX_VALUE);}\n27:     static long bounded(String key,long fallback,long low,long high){\n28:         long value=Long.parseLong(Config.get(key,Long.toString(fallback)));\n29:         if(value<low || value>high)throw new IllegalArgumentException(\"Invalid \"+key);return value;\n30:     }\n31:     static void validateConfiguration(){minutes();windowSeconds();minimumRecent();\n32:         if(Config.getLong(\"ape.jev.regionBlocking.updateIntervalMs\",30000)<=0)throw new IllegalArgumentException(\"Invalid Region interval\");}\n33: "},{"start":169,"end":211,"text":"169:         Analysis compute(JevRegion.Snapshot s,Stats stats){\n170:             if(version!=s.abstraction){stamps.clear();version=s.abstraction;}\n171:             List<Candidate> candidates=new ArrayList<Candidate>();\n172:             List<Region> regions=calculator.structure(s);\n173:             for(Region region:regions){\n174:                 if(Thread.currentThread().isInterrupted())throw new CancellationException();\n175:                 Candidate c=new Candidate(region);c.lastProgress=Long.MIN_VALUE;\n176:                 for(int v:region.members){c.visits+=stats.visits[v];c.recent+=stats.recent[v];c.actions+=stats.actionCount[v];c.unvisited+=stats.unvisited[v];\n177:                 }\n178:                 for(int v:region.members)if(stats.unknown.containsKey(v))c.noveltyStatus=\"UNKNOWN\";\n179:                 for(int[] edge:stats.recentTransitions)if(!region.members.contains(edge[0]) && region.members.contains(edge[1]))c.reentries++;\n180:                 c.average=(double)c.visits/region.members.size();\n181:                 for(Discovery event:stats.discoveries)if(region.members.contains(event.source)){\n182:                     if(event.known){c.lastProgress=Math.max(c.lastProgress,event.time);if(recent(event.time,stats))c.newStates++;}\n183:                     else if(recent(event.time,stats))c.noveltyStatus=\"UNKNOWN\";\n184:                 }\n185:                 Stamp old=stamps.get(region.header);c.membershipChanged=old!=null && !old.members.equals(region.members);\n186:                 stamps.put(region.header,new Stamp(region.members));\n187:                 for(JevRegion.Concrete concrete:s.entries)if(!region.members.contains(concrete.source)){\n188:                     Entry entry=new Entry(concrete,region);if(entry.inside.contains(region.header))c.entries.add(entry);\n189:                 }\n190:                 Collections.sort(c.entries,new Comparator<Entry>(){public int compare(Entry a,Entry b){return Integer.compare(a.concrete.id,b.concrete.id);}});\n191:                 boolean reviewable=false;for(Entry e:c.entries)reviewable |= e.concrete.eligible;\n192:                 c.reason=c.entries.isEmpty()?\"no_entry\":!reviewable?\"no_reviewable_entry\":c.average<=2?\"avg_visits_not_above_2\":c.recent<minRecent?\"insufficient_recent_visits\":\n193:                     !c.noveltyStatus.equals(\"KNOWN\")?\"novelty_unknown\":c.lastProgress>stats.now-stats.window?\"recent_region_progress\":\"mature\";\n194:                 c.mature=c.reason.equals(\"mature\");candidates.add(c);\n195:             }\n196:             List<Candidate> ranked=new ArrayList<Candidate>(candidates);\n197:             Collections.sort(ranked,new Comparator<Candidate>(){public int compare(Candidate a,Candidate b){int size=Integer.compare(a.region.members.size(),b.region.members.size());return size!=0?size:Integer.compare(a.region.header,b.region.header);}});\n198:             Set<Integer> selectedMembers=new HashSet<Integer>(),requested=new HashSet<Integer>();\n199:             for(Candidate c:ranked)if(c.mature){\n200:                 if(!Collections.disjoint(selectedMembers,c.region.members)){c.reason=\"nested_deferred\";continue;}\n201:                 c.selected=true;selectedMembers.addAll(c.region.members);\n202:                 for(Entry e:c.entries){\n203:                     e.status=e.concrete.eligible?\"ready_for_review\":\"unconfirmed_or_unmatchable\";\n204:                     if(e.concrete.eligible)requested.add(e.concrete.id);\n205:                 }\n206:             }\n207:             // Legacy saturation/guard computation is comparison telemetry only. It\n208:             // cannot filter new nominations, including mixed-target concretes.\n209:             return new Analysis(s,stats,candidates,compareLegacy?calculator.compute(s):null,Collections.unmodifiableSet(new TreeSet<Integer>(requested)));\n210:         }\n211:         static boolean recent(long time,Stats stats){return time>stats.now-stats.window && time<=stats.now;}"}]},{"path":"native/src/com/android/commands/monkey/ape/jev/JevRegistry.java","sha256":"1f6ab9e42e01565c9831c8b054ee4bbce4d39ff81bfca813adacbd4444b988b3","excerpts":[{"start":315,"end":383,"text":"315:     ConfirmedHistory confirmedHistory(State state) {\n316:         long profileStart=JevReviewProfile.start();\n317:         long begin=System.nanoTime();ConfirmedHistory view=new ConfirmedHistory();\n318:         int before=confirmedInputs.size();\n319:         view.complete=confirmationHistoryComplete && confirmationModel!=null && confirmationModel.getVersion()==version\n320:             && JevHistoryAudit.identityContains(confirmationModel.getGraph().getStates(),state);\n321:         if(confirmationModel==null){view.enumerationNanos=System.nanoTime()-begin;JevReviewProfile.end(\"history_scan_group_sort\",profileStart);return view;}\n322:         for(GUITreeAction input:confirmedInputs) {\n323:             JevDeadline.check();view.total++;\n324:             if(confirmedMappingProblem(input)!=null){view.unknown++;continue;}\n325:             if(input.getGUITree().getCurrentState()!=state)continue;\n326:             ModelAction action=input.getModelAction();\n327:             if(!action.requireTarget())continue;\n328:             List<GUITreeAction> group=view.groups.get(action);\n329:             if(group==null){group=new ArrayList<GUITreeAction>();view.groups.put(action,group);}group.add(input);\n330:         }\n331:         for(List<GUITreeAction> group:view.groups.values())Collections.sort(group,new Comparator<GUITreeAction>() {\n332:             public int compare(GUITreeAction a,GUITreeAction b) {\n333:                 int c=Integer.compare(a.getGUITree().getTimestamp(),b.getGUITree().getTimestamp());\n334:                 if(c==0)c=Integer.compare(a.getGUITree().getId(),b.getGUITree().getId());\n335:                 if(c==0)c=ConcreteActionIdentity.of(a.getActionType().name(),a.getGUITreeNode()).toString()\n336:                     .compareTo(ConcreteActionIdentity.of(b.getActionType().name(),b.getGUITreeNode()).toString());\n337:                 return c;\n338:             }\n339:         });\n340:         view.complete &= view.unknown==0 && before==confirmedInputs.size() && confirmationModel.getVersion()==version;\n341:         view.enumerationNanos=System.nanoTime()-begin;JevReviewProfile.end(\"history_scan_group_sort\",profileStart);return view;\n342:     }\n343:     int confirmationCount(){return confirmedInputs.size();}\n344:     private boolean confirmedExact(GUITreeAction candidate) {\n345:         long profileStart=JevReviewProfile.start(),examined=0;\n346:         try {\n347:         if(confirmationModel==null)return false;\n348:         for(GUITreeAction prior:confirmedInputs) {\n349:             examined++;\n350:             JevDeadline.check();\n351:             if(prior.getModelAction()!=candidate.getModelAction())continue;\n352:             if(confirmedMappingProblem(prior)==null && sameConcrete(candidate,prior))return true;\n353:         }\n354:         return false;\n355:         } finally {JevReviewProfile.end(\"confirmed_exact\",profileStart);JevReviewProfile.add(\"confirmed_inputs_examined\",0,examined);}\n356:     }\n357: \n358:     /** Exact execution in the current State/tree. This never consults the cross-State index. */\n359:     public boolean hasExactExecution(State state,ModelAction action,GUITree tree,GUITreeNode node) {\n360:         if(state==null || action==null || tree==null || node==null || tree.getCurrentState()!=state)return false;\n361:         long profileStart=JevReviewProfile.start();\n362:         try {GUITreeAction candidate=new GUITreeAction(tree,node,action);\n363:             return hardMatch(candidate)!=null || confirmedExact(candidate);\n364:         } finally {JevReviewProfile.end(\"exact_execution_filter\",profileStart);}\n365:     }\n366: \n367:     /** Confirmed concrete execution in any State of the same activity. */\n368:     public boolean hasRelatedConcreteExecution(String actionType,String sourceActivity,String canonicalFullName) {\n369:         if(actionType==null || sourceActivity==null || canonicalFullName==null || canonicalFullName.length()==0)return false;\n370:         ConcreteActionIdentity identity=new ConcreteActionIdentity(actionType,canonicalFullName);\n371:         List<Execution> values=relatedIndex.get(relatedKey(sourceActivity,identity));\n372:         if(values!=null && !values.isEmpty())return true;\n373:         // Input may be confirmed before its transition is observed/indexed.\n374:         // Consult the existing authority; do not invent another history index.\n375:         for(GUITreeAction input:confirmedInputs) {\n376:             if(input.getGUITreeNode()!=null && confirmedMappingProblem(input)==null && input.getActionType().name().equals(actionType)\n377:                     && sourceActivity.equals(input.getModelAction().getState().getActivity())\n378:                     && identity.equals(ConcreteActionIdentity.of(actionType,input.getGUITreeNode())))return true;\n379:         }\n380:         return false;\n381:     }\n382:     private static String relatedKey(String activity,ConcreteActionIdentity identity) {\n383:         return new JSONArray().put(identity.actionType()).put(activity).put(identity.canonicalFullName()).toString();"},{"start":697,"end":728,"text":"697:     static GUITreeNode correspondingNode(GUITreeAction source,GUITree tree,ModelAction action) {\n698:         if(source==null || tree==null || action==null || source.getGUITreeNode()==null)return null;\n699:         GUITree original=source.getGUITree();GUITreeNode node=source.getGUITreeNode();\n700:         if(source.getActionType()!=action.getType())return null;\n701:         ConcreteActionIdentity identity=lookupIdentity(source.getActionType().name(),node);\n702:         if(original==tree)return uniqueIdentityNode(tree,identity)==node?node:null;\n703:         if(uniqueIdentityNode(original,identity)!=node)return null;\n704:         return uniqueIdentityNode(tree,identity);\n705:     }\n706:     /** Audit only: count the exact existing identity relation without rebinding or relaxing it. */\n707:     static JSONObject bindingDiagnostic(final GUITreeAction source,final GUITree tree,final ModelAction action) {\n708:         try {return com.android.commands.monkey.ape.naming.NameManager.withoutInterning(new java.util.function.Supplier<JSONObject>(){public JSONObject get(){\n709:             if(source==null||source.getGUITree()==null||source.getGUITreeNode()==null||tree==null||action==null)\n710:                 return fields(\"reason\",\"missing_source_tree_or_action\",\"source_match_count\",-1,\"target_match_count\",-1);\n711:             ConcreteActionIdentity identity=ConcreteActionIdentity.of(source.getActionType().name(),source.getGUITreeNode());\n712:             int original=identityCount(source.getGUITree(),identity),current=identityCount(tree,identity);\n713:             String reason=source.getActionType()!=action.getType()?\"action_type_mismatch\":original!=1?\"source_identity_not_unique\":\n714:                 current==0?\"target_node_absent\":current>1?\"target_node_ambiguous\":\"unique_identity_match\";\n715:             return fields(\"reason\",reason,\"source_match_count\",original,\"target_match_count\",current,\"concrete_identity\",identity.toString());\n716:         }});}catch(Exception unavailable){return fields(\"reason\",\"diagnostic_unavailable\",\"source_match_count\",-1,\"target_match_count\",-1);}\n717:     }\n718:     private static int identityCount(GUITree tree,ConcreteActionIdentity identity) {\n719:         if(tree==null||tree.getRootNode()==null)return 0;\n720:         int count=0;Deque<GUITreeNode> nodes=new ArrayDeque<GUITreeNode>();nodes.add(tree.getRootNode());\n721:         while(!nodes.isEmpty()) {GUITreeNode node=nodes.removeFirst();if(identity.equals(ConcreteActionIdentity.of(identity.actionType(),node)))count++;\n722:             Iterator<GUITreeNode> children=node.getChildren();while(children.hasNext())nodes.addLast(children.next());}\n723:         return count;\n724:     }\n725:     private boolean sameConcrete(GUITreeAction a,GUITreeAction b) {\n726:         return a!=null && b!=null && a.getActionType()==b.getActionType()\n727:             && a.getGUITree().getCurrentState()==b.getGUITree().getCurrentState()\n728:             && correspondingNode(a,b.getGUITree(),b.getModelAction())==b.getGUITreeNode();"},{"start":802,"end":866,"text":"802:     private boolean related(Execution e,String actionType,String sourceActivity,Member candidate) {\n803:         if(!e.member.type.equals(actionType))return false;\n804:         if(!e.sourceActivities.contains(sourceActivity==null?\"\":sourceActivity))return false;\n805:         return !e.member.fullName.isEmpty() && new ConcreteActionIdentity(e.member.type,e.member.fullName)\n806:             .equals(new ConcreteActionIdentity(actionType,candidate.fullName));\n807:     }\n808:     private boolean relatedToAny(Execution e,String actionType,String sourceActivity,List<Member> candidates) {\n809:         for(Member candidate:candidates)if(related(e,actionType,sourceActivity,candidate))return true;\n810:         return false;\n811:     }\n812:     private boolean sameStateAction(Execution e,String actionType,State state,ModelAction modelAction) {\n813:         if(e.anchor==null || !belongsToState(state,e.anchor.tree) || !e.member.type.equals(actionType))return false;\n814:         return modelAction!=null && e.concreteAction!=null && e.concreteAction.getModelAction()==modelAction;\n815:     }\n816:     private boolean belongsToState(State state,GUITree tree) {\n817:         if(state==null || tree==null)return false;\n818:         for(GUITree candidate:state.getGUITrees())if(candidate==tree)return true;\n819:         return false;\n820:     }\n821:     private JSONArray history(List<GUITreeAction> currentActions,String actionType,String sourceActivity,State state,ModelAction modelAction,List<Member> candidates,List<Execution> selected,JSONObject contexts) throws JSONException {\n822:         List<Execution> sameStateAction=new ArrayList<Execution>(), relatedOther=new ArrayList<Execution>();\n823:         Set<Execution> relevant=Collections.newSetFromMap(new IdentityHashMap<Execution,Boolean>());\n824:         if(!currentActions.isEmpty())relevant.addAll(indexed(executionIndex,currentActions.get(0)));\n825:         for(Member member:candidates) {\n826:             List<Execution> related=relatedIndex.get(relatedKey(sourceActivity==null?\"\":sourceActivity,\n827:                 new ConcreteActionIdentity(actionType,member.fullName)));\n828:             if(related!=null)relevant.addAll(related);\n829:         }\n830:         for(Execution e:relevant) {\n831:             boolean current=false;\n832:             for(GUITreeAction action:currentActions)if(sameConcrete(action,e.concreteAction)){current=true;break;}\n833:             if(current)continue;\n834:             if(sameStateAction(e,actionType,state,modelAction))sameStateAction.add(e);\n835:             else if(belongsToState(state,e.anchor.tree))continue;\n836:             else if(relatedToAny(e,actionType,sourceActivity,candidates))relatedOther.add(e);\n837:         }\n838:         Comparator<Execution> order=new Comparator<Execution>() {public int compare(Execution a,Execution b) {\n839:             String x=a.transitions.isEmpty()?\"\":a.transitions.get(0),y=b.transitions.isEmpty()?\"\":b.transitions.get(0);\n840:             int compared=x.compareTo(y);if(compared!=0)return compared;\n841:             refreshExecutionOrder();return Integer.compare(executionOrder.get(a),executionOrder.get(b));\n842:         }};\n843:         Collections.sort(sameStateAction,order);Collections.sort(relatedOther,order);\n844:         sameStateAction.addAll(relatedOther);\n845:         List<Execution> remaining=new ArrayList<Execution>();\n846:         for(Execution e:sameStateAction) {\n847:             Execution combined=null;\n848:             for(Execution existing:remaining)if(existing.anchor.tree.getCurrentState()==e.anchor.tree.getCurrentState()\n849:                     && existing.concreteAction.getModelAction()==e.concreteAction.getModelAction()\n850:                     && existing.member.fullName.equals(e.member.fullName)){combined=existing;break;}\n851:             if(combined==null) {\n852:                 combined=new Execution(e.member,e.anchor.tree.getCurrentState().getActivity(),e.anchor,e.concreteAction);\n853:                 remaining.add(combined);\n854:             }\n855:             mergeExecution(combined,e);\n856:         }\n857:         List<Execution> preferred=new ArrayList<Execution>();\n858:         for(Member candidate:candidates) {\n859:             boolean matched=false;\n860:             for(Execution e:preferred)if(related(e,actionType,sourceActivity,candidate)){matched=true;break;}\n861:             if(matched)continue;\n862:             for(Execution e:remaining) {\n863:                 if(!belongsToState(state,e.anchor.tree) && related(e,actionType,sourceActivity,candidate)) {\n864:                     preferred.add(e);break;\n865:                 }\n866:             }"}]},{"path":"native/src/com/android/commands/monkey/ape/jev/ConcreteActionIdentity.java","sha256":"17b1ccffaa18a863b342f75c67b508c0b7854756480c69dde6825b94580c95e6","excerpts":[{"start":1,"end":74,"text":"1: package com.android.commands.monkey.ape.jev;\n2: \n3: import com.android.commands.monkey.ape.tree.GUITreeNode;\n4: \n5: /**\n6:  * Stable identity of one concrete action. Scope such as Activity or State is\n7:  * deliberately supplied by the caller and is never folded into this value.\n8:  */\n9: public final class ConcreteActionIdentity {\n10:     private final String actionType;\n11:     private final String canonicalFullName;\n12: \n13:     public ConcreteActionIdentity(String actionType, String canonicalFullName) {\n14:         if (actionType == null || actionType.length() == 0)\n15:             throw new IllegalArgumentException(\"actionType must not be empty\");\n16:         if (canonicalFullName == null || canonicalFullName.length() == 0)\n17:             throw new IllegalArgumentException(\"canonicalFullName must not be empty\");\n18:         this.actionType = actionType;\n19:         this.canonicalFullName = canonicalFullName;\n20:     }\n21: \n22:     public static ConcreteActionIdentity of(String actionType, GUITreeNode node) {\n23:         if (node == null) throw new IllegalArgumentException(\"node must not be null\");\n24:         return new ConcreteActionIdentity(actionType, canonical(node));\n25:     }\n26: \n27:     /**\n28:      * Production nodes use the exact native fullName.  Small JVM fixtures may\n29:      * omit optional accessibility strings that the legacy Name renderer\n30:      * assumes are non-null; use a deterministic attribute chain there rather\n31:      * than making identity lookup crash or guessing from bounds.\n32:      */\n33:     public static String canonical(final GUITreeNode node) {\n34:         // Observing an identity returns a string, never a native Name. Do not\n35:         // assign global Name order to controls merely inspected by review.\n36:         long start=JevReviewProfile.start();\n37:         try {return com.android.commands.monkey.ape.naming.NameManager.withoutInterning(\n38:             new java.util.function.Supplier<String>() {public String get(){return canonicalReadOnly(node);}});\n39:         } finally {JevReviewProfile.end(\"canonical_render\",start);}\n40:     }\n41: \n42:     private static String canonicalReadOnly(GUITreeNode node) {\n43:         try { return JevIdentity.fullName(node).toXPath(); }\n44:         catch (RuntimeException unavailable) {\n45:             StringBuilder out=new StringBuilder(\"fallback:\");\n46:             for(GUITreeNode current=node;current!=null;current=current.getParent()) {\n47:                 out.append('[').append(String.valueOf(current.getClassName())).append('|')\n48:                     .append(String.valueOf(current.getResourceID())).append('|').append(current.getIndex()).append('|')\n49:                     .append(String.valueOf(JevIdentity.text(current))).append('|').append(String.valueOf(current.getContentDesc()))\n50:                     .append('|').append(current.isClickable()).append('|').append(current.isLongClickable()).append('|')\n51:                     .append(current.isCheckable()).append('|').append(current.isScrollable()).append(']');\n52:             }\n53:             return out.toString();\n54:         }\n55:     }\n56: \n57:     public String actionType() { return actionType; }\n58:     public String canonicalFullName() { return canonicalFullName; }\n59: \n60:     @Override public int hashCode() {\n61:         return 31 * actionType.hashCode() + canonicalFullName.hashCode();\n62:     }\n63: \n64:     @Override public boolean equals(Object other) {\n65:         if (!(other instanceof ConcreteActionIdentity)) return false;\n66:         ConcreteActionIdentity value = (ConcreteActionIdentity) other;\n67:         return actionType.equals(value.actionType)\n68:             && canonicalFullName.equals(value.canonicalFullName);\n69:     }\n70: \n71:     @Override public String toString() {\n72:         return actionType + \"|\" + canonicalFullName;\n73:     }\n74: }"}]},{"path":"native/src/com/android/commands/monkey/ape/jev/JevIdentity.java","sha256":"ad8b4e330097ec3b2aa134000143afa18f790c8d3626a32536fddf750a5a0850","excerpts":[{"start":25,"end":75,"text":"25: /**\n26:  * Provenance-aware identity for Jev concrete controls.\n27:  *\n28:  * <p>Jev cross-GUI concrete fullName must ignore ONLY the synthetic image-hash\n29:  * text that APE generates at the bitmap hashing write in\n30:  * {@link GUITreeNode#computeAndSetImageText(android.graphics.Bitmap)}\n31:  * (recorded through {@link GUITreeNode#setGeneratedImageText(String)}). Real\n32:  * text -- including text that literally looks like \"#1234\" -- content-desc,\n33:  * index, ancestor naming, class/resource id, and action flags are never\n34:  * altered, and the marker is never inferred from string content.\n35:  *\n36:  * <p>This helper does not mutate live nodes, cached Names, or global naming\n37:  * configuration. For nodes whose own text and every ancestor carry no\n38:  * synthetic image-hash provenance, {@link #fullName(GUITreeNode)} returns the\n39:  * exact same cached Name instance the native full namer produces for the live\n40:  * node.\n41:  */\n42: public final class JevIdentity {\n43: \n44:     private JevIdentity() {\n45:     }\n46: \n47:     /**\n48:      * Returns the node text, or the empty string when the current text is the\n49:      * synthetic image-hash write. Ordinary text is returned exactly.\n50:      */\n51:     public static String text(GUITreeNode node) {\n52:         if (node == null) {\n53:             throw new IllegalArgumentException(\"node must not be null\");\n54:         }\n55:         return node.isGeneratedImageText() ? \"\" : node.getText();\n56:     }\n57: \n58:     /**\n59:      * Returns the node's full native name (type, text, index, ancestor path,\n60:      * and action patch) with every synthetic image-hash text in the chain\n61:      * normalized to the empty string. Ordinary nodes keep their names exactly.\n62:      */\n63:     public static Name fullName(GUITreeNode node) {\n64:         if (node == null) {\n65:             throw new IllegalArgumentException(\"node must not be null\");\n66:         }\n67:         for (GUITreeNode n = node; n != null; n = n.getParent()) {\n68:             if (n.isGeneratedImageText()) return NamerFactory.fullNamer().naming(shadowChain(node));\n69:         }\n70:         return NamerFactory.fullNamer().naming(node);\n71:     }\n72: \n73:     /**\n74:      * Builds a throwaway copy of the node's ancestor chain (root to node,\n75:      * inclusive) so the shared full namer can be evaluated without touching"}]},{"path":"native/src/com/android/commands/monkey/ape/jev/JevRuntime.java","sha256":"e5b22f7d4a5613f50c24938d3cf06d49da186078f8dc873c8084f79583cc535e","excerpts":[{"start":900,"end":945,"text":"900:                         \"action_fingerprint\",action.getActionFingerprint()));\n901:                 if(++batch%32==0)output.drain();\n902:             }\n903:         }\n904:         output.drain();\n905:     }\n906: \n907:     private void writeGraphSnapshot() {\n908:         if(lastModel==null)return;\n909:         try {\n910:             Graph graph=lastModel.getGraph();JSONObject snapshot=new JSONObject();\n911:             snapshot.put(\"event\",\"graph_snapshot\").put(\"abstraction_version\",registry.version()).put(\"graph_step\",step);\n912:             JSONArray roots=new JSONArray();for(State state:graph.getEntryStates())roots.put(state.getGraphId());snapshot.put(\"roots\",roots);\n913:             JSONArray states=new JSONArray(),edges=new JSONArray();\n914:             Set<StateTransition> allEdges=new HashSet<StateTransition>();\n915:             for(State state:graph.getStates()) {\n916:                 JSONObject item=stateTelemetry(state,\"close\");item.put(\"id\",state.getGraphId());\n917:                 item.put(\"activity\",String.valueOf(state.getActivity()));item.put(\"visits\",state.getVisitedCount());\n918:                 item.put(\"first_seen\",state.getFirstVisitedTimestamp());item.put(\"last_seen\",state.getLastVisitedTimestamp());\n919:                 JSONArray shots=new JSONArray();\n920:                 String captured=stateScreenshotPaths.get(state.getGraphId());\n921:                 if(captured!=null)shots.put(captured);\n922:                 else for(GUITree tree:state.getGUITrees()) {String path=relativeImagePath(tree.getJevImage());if(path!=null){shots.put(path);break;}}\n923:                 item.put(\"screenshot_paths\",shots).put(\"screenshot_status\",shots.length()>0?\"saved\":screenshotFailureReasons.containsKey(state.getGraphId())?\n924:                     screenshotFailureReasons.get(state.getGraphId()):\"not_observed_at_safe_point\")\n925:                     .put(\"screenshot_failure_count\",screenshotFailures.containsKey(state.getGraphId())?screenshotFailures.get(state.getGraphId()):0);\n926:                 item.put(\"model_actions\",graphActionDetails(state));states.put(item);\n927:                 allEdges.addAll(graph.getOutStateTransitions(state));\n928:             }\n929:             for(StateTransition edge:allEdges) {\n930:                 JSONObject item=new JSONObject();item.put(\"id\",edge.getGraphId()).put(\"source\",edge.getSource().getGraphId())\n931:                     .put(\"target\",edge.getTarget().getGraphId()).put(\"action\",edge.getAction().getGraphId())\n932:                     .put(\"action_fingerprint\",edge.getAction().getActionFingerprint()).put(\"target_activity\",String.valueOf(edge.getTarget().getActivity()))\n933:                     .put(\"type\",String.valueOf(edge.getType())).put(\"visits\",edge.getVisitedCount()).put(\"is_circle\",edge.isCircle())\n934:                     .put(\"first_seen\",edge.getFirstVisitedTimestamp()).put(\"last_seen\",edge.getLastVisitedTimestamp());edges.put(item);\n935:             }\n936:             snapshot.put(\"states\",states).put(\"edges\",edges);\n937:             output.save(graphSnapshotFile,snapshot,false);\n938:         } catch(Exception e) {output.fail(e);}\n939:     }\n940: \n941:     private JSONArray graphActionDetails(State state) throws JSONException {\n942:         JSONArray actions=new JSONArray();\n943:         for(ModelAction action:state.getActions()) {\n944:             JSONObject item=new JSONObject().put(\"id\",action.getGraphId()).put(\"type\",action.getType().name())\n945:                 .put(\"visits\",action.getVisitedCount()).put(\"unvisited\",action.isUnvisited())"}]},{"path":"native/src/com/android/commands/monkey/ape/model/StateKey.java","sha256":"0571fa722b7a09ba445124d6e729d85200be19b7e4860ca03741826a616ca36c","excerpts":[{"start":42,"end":86,"text":"42:     private Name[] widgets;\n43:     private int hashCode;\n44: \n45:     public StateKey(ComponentName activity, Naming naming, Name[] widgets) {\n46:         this.activity = activity.getClassName();\n47:         this.naming = naming;\n48:         this.widgets = widgets;\n49:     }\n50: \n51:     @Override\n52:     public int hashCode() {\n53:         if (hashCode == 0) {\n54:             final int prime = 31;\n55:             int result = 1;\n56:             result = prime * result + ((activity == null) ? 0 : activity.hashCode());\n57:             result = prime * result + ((naming == null) ? 0 : naming.hashCode());\n58:             result = prime * result + Arrays.hashCode(widgets);\n59:             hashCode = result;\n60:         }\n61:         return hashCode;\n62:     }\n63: \n64:     @Override\n65:     public boolean equals(Object obj) {\n66:         if (this == obj)\n67:             return true;\n68:         if (obj == null)\n69:             return false;\n70:         if (getClass() != obj.getClass())\n71:             return false;\n72:         StateKey other = (StateKey) obj;\n73:         if (activity == null) {\n74:             if (other.activity != null)\n75:                 return false;\n76:         } else if (!activity.equals(other.activity))\n77:             return false;\n78:         if (naming == null) {\n79:             if (other.naming != null)\n80:                 return false;\n81:         } else if (!naming.equals(other.naming))\n82:             return false;\n83:         if (!Arrays.equals(widgets, other.widgets))\n84:             return false;\n85:         return true;\n86:     }"}]},{"path":"native/src/com/android/commands/monkey/ape/model/Graph.java","sha256":"5676b123e0aaf93065e72c76ac33aab20d738b0a7262415977c8f1aa35a80022","excerpts":[{"start":374,"end":395,"text":"374:     public StateTransition addTransition(State source, ModelAction action, State target, GUITree sourceTree,\n375:             GUITreeAction treeAction, GUITree targetTree) {\n376:         StateTransition edge = addStateTransition(source, action, target);\n377:         if (edge == null) {\n378:             return null;\n379:         }\n380:         GUITreeTransition treeTransition = new GUITreeTransition(sourceTree, treeAction, targetTree);\n381:         treeTransition.setThrottle(action.getThrottle());\n382:         edge.updateThrottle(treeTransition.getThrottle());\n383:         stateTransitionHistory.add(edge);\n384:         treeTransitionHistory.add(treeTransition);\n385:         edge.append(treeTransition);\n386: \n387:         edge.strengthen();\n388:         markVisited(edge, timestamp);\n389:         fireStateTransitionEvents(edge);\n390:         if (this.entryGUITrees.contains(sourceTree)) {\n391:             this.entryStates.add(source);\n392:         }\n393:         if (this.cleanEntryGUITrees.contains(sourceTree)) {\n394:             this.cleanEntryStates.add(source);\n395:         }"}]},{"path":"native/src/com/android/commands/monkey/ape/jev/JevHistoryPairwiseProtocol.java","sha256":"5dd867d2679205aa5867078cec3079d86c2e116c815741dbbc1c16fe109ab5c6","excerpts":[{"start":200,"end":245,"text":"200:     /** Attribute ranking only; equal signatures are NOT asserted to be semantic equivalents. */\n201:     static List<String> selectHistory(JSONObject candidate,Map<String,JSONObject> history)throws JSONException {\n202:         final Map<String,Set<String>> features=new LinkedHashMap<String,Set<String>>();\n203:         for(String id:history.keySet()){JevDeadline.check();features.put(id,selectionFeatures(history.get(id)));}\n204:         return selectHistory(candidate,history.keySet(),features);\n205:     }\n206:     static List<String> selectHistory(JSONObject candidate,Collection<String> historyIds,Map<String,Set<String>> features)throws JSONException {\n207:         return selectHistoryFeatures(selectionFeatures(candidate),historyIds,features);\n208:     }\n209:     static List<String> selectHistoryFeatures(Set<String> wanted,Collection<String> historyIds,Map<String,Set<String>> features)throws JSONException {\n210:         final Map<String,Integer> scores=new HashMap<String,Integer>();\n211:         List<String> ranked=new ArrayList<String>(historyIds);\n212:         for(String id:ranked){JevDeadline.check();Set<String> f=features.get(id);\n213:             if(f==null)throw new JSONException(\"missing cached history selection features\");\n214:             int score=0;for(String value:f)if(wanted.contains(value))score+=value.startsWith(\"label:\")?100:value.startsWith(\"word:\")?10:value.startsWith(\"resource_id:\")?8:2;\n215:             scores.put(id,score);}\n216:         // Stable sort preserves the Registry's chronological / identity tie order.\n217:         Collections.sort(ranked,new Comparator<String>(){public int compare(String a,String b){return Integer.compare(scores.get(b),scores.get(a));}});\n218:         List<String> selected=new ArrayList<String>();Set<Set<String>> seen=new HashSet<Set<String>>();\n219:         while(!ranked.isEmpty() && selected.size()<MAX_HISTORY){\n220:             JevDeadline.check();String next=ranked.get(0);\n221:             if(!selected.isEmpty())for(String id:ranked)if(!seen.contains(features.get(id))){next=id;break;}\n222:             selected.add(next);seen.add(features.get(next));ranked.remove(next);\n223:         }\n224:         return selected;\n225:     }\n226:     static Set<String> selectionFeatures(JSONObject control)throws JSONException {\n227:         Set<String> out=new TreeSet<String>();if(control==null)return out;\n228:         addFeatures(control,out);JSONArray subtree=control.optJSONArray(\"target_subtree\");\n229:         if(subtree!=null)for(int i=0;i<subtree.length();i++)addFeatures(subtree.getJSONObject(i),out);\n230:         return out;\n231:     }\n232:     private static void addFeatures(JSONObject node,Set<String> out)throws JSONException {\n233:         for(String field:new String[]{\"text\",\"content_desc\",\"resource_id\",\"class\",\"action_type\"}) {\n234:             addSelectionFeature(field,node.optString(field,\"\"),out);\n235:         }\n236:     }\n237:     static void addSelectionFeature(String field,String raw,Set<String> out) {\n238:         String value=raw.trim().toLowerCase(Locale.ROOT);if(value.isEmpty())return;\n239:         if(field.equals(\"text\")||field.equals(\"content_desc\")){\n240:             out.add(\"label:\"+value);for(String word:value.split(\"[^\\\\p{L}\\\\p{N}]+\"))if(!word.isEmpty())out.add(\"word:\"+word);\n241:         }else out.add(field+\":\"+value);\n242:     }\n243:     private JevHistoryPairwiseProtocol(){}\n244: }"}]},{"path":"native/src/com/android/commands/monkey/ape/jev/JevSemanticReview.java","sha256":"d582cdc79cd45fb0931ce05ca835cdc291f2c7cf2e6c367ae7002155dff50c4a","excerpts":[{"start":610,"end":621,"text":"610:         return com.android.commands.monkey.ape.naming.NameManager.withoutInterning(new java.util.function.Supplier<Page>(){\n611:             public Page get(){return buildPage(state,tree,include,descriptors);}\n612:         });\n613:     }\n614:     private Page buildPage(State state,GUITree tree,Set<String> include){return buildPage(state,tree,include,null);}\n615:     private Page buildPage(State state,GUITree tree,Set<String> include,Map<String,Candidate> descriptors) {\n616:         long began=System.nanoTime();\n617:         try {\n618:             JevRegistry.ConfirmedHistory history=registry.confirmedHistory(state);\n619:             long evidenceStart=System.nanoTime();\n620:             Map<String,Candidate> candidates=new LinkedHashMap<String,Candidate>();Set<String> ambiguous=new HashSet<String>();int number=0;\n621:             if(descriptors!=null){for(Candidate c:descriptors.values())if(include.contains(c.key))candidates.put(c.key,c);}"},{"start":650,"end":698,"text":"650:                 JevReviewProfile.end(\"candidate_descriptor\",descriptorStartCurrent);\n651:                 long richStart=JevReviewProfile.start();\n652:                 JSONObject control=descriptors==null?JevEvidence.pairAction(new com.android.commands.monkey.ape.tree.GUITreeAction(tree,c.node,c.action),pageId):null;\n653:                 if(descriptors==null)JevReviewProfile.end(\"candidate_rich\",richStart);\n654:                 if(control!=null)current.put(c.candidateId,control);\n655:                 List<com.android.commands.monkey.ape.tree.GUITreeAction> members=history.members(c.action);\n656:                 Map<String,Set<String>> featurePool=new LinkedHashMap<String,Set<String>>();\n657:                 for(com.android.commands.monkey.ape.tree.GUITreeAction h:members) {\n658:                     JevDeadline.check();String hid=historyIds.get(h);\n659:                     if(hid==null) {\n660:                         hid=\"h\"+(historyIds.size()+1);historyIds.put(h,hid);\n661:                         historyById.put(hid,h);\n662:                         sourcePage(h.getGUITree(),pages,pageIds); // preserve old Page ID allocation order\n663:                         long descriptorStart=JevReviewProfile.start();\n664:                         JevEvidence.PairDescriptor descriptor=JevEvidence.pairDescriptor(h);\n665:                         JevReviewProfile.end(\"history_descriptor\",descriptorStart);\n666:                         historyDescriptors.put(h,descriptor);\n667:                         if(descriptor.recoverable)recoverableHistoryCount++;\n668:                         provenance.put(hid,new JSONObject().put(\"source_tree\",h.getGUITree().getId())\n669:                             .put(\"source_gui_timestamp\",h.getGUITree().getTimestamp()).put(\"current_state\",state.getGraphId())\n670:                             .put(\"current_model_action\",h.getModelAction().getGraphId()).put(\"current_version\",modelVersion)\n671:                             .put(\"input_confirmed\",true).put(\"confirmation_basis\",\"live confirmedInputs before review; not function completion\")\n672:                             .put(\"attributes_recoverable\",descriptor.recoverable));\n673:                     }\n674:                     JevEvidence.PairDescriptor descriptor=historyDescriptors.get(h);\n675:                     if(descriptor!=null && descriptor.recoverable)featurePool.put(hid,descriptor.selectionFeatures);\n676:                 }\n677:                 long rankStart=JevReviewProfile.start();\n678:                 List<String> selected=descriptors==null?(control==null?Collections.<String>emptyList():JevHistoryPairwiseProtocol.selectHistory(control,featurePool.keySet(),featurePool))\n679:                     :(!candidateDescriptor.recoverable?Collections.<String>emptyList():JevHistoryPairwiseProtocol.selectHistoryFeatures(candidateDescriptor.selectionFeatures,featurePool.keySet(),featurePool));\n680:                 JevReviewProfile.end(\"history_ranking\",rankStart);\n681:                 if(descriptors!=null && !selected.isEmpty()){\n682:                     long currentRich=JevReviewProfile.start();control=JevEvidence.pairAction(new com.android.commands.monkey.ape.tree.GUITreeAction(tree,c.node,c.action),pageId);\n683:                     JevReviewProfile.end(\"candidate_rich\",currentRich);if(control==null)throw new IllegalStateException(\"selected candidate became unrecoverable\");\n684:                     current.put(c.candidateId,control);\n685:                 }\n686:                 long pairStart=JevReviewProfile.start();JSONArray selectedIds=new JSONArray();\n687:                 for(String hid:selected){\n688:                     selectedIds.put(hid);usedHistory.add(hid);c.auditHistory.put(hid,historyById.get(hid));\n689:                     pairs.put(new JSONObject().put(\"id\",\"p\"+(pairs.length()+1)).put(\"candidate\",c.candidateId).put(\"history\",hid));\n690:                 }\n691:                 JevReviewProfile.end(\"pair_generation\",pairStart);\n692:                 coverage.put(c.candidateId,new JSONObject().put(\"legal_history_count\",members.size()).put(\"complete\",history.complete && featurePool.size()==members.size())\n693:                     .put(\"history_collection_complete\",history.complete).put(\"recoverable_history_count\",featurePool.size()).put(\"selected_history\",selected.size()).put(\"selected_history_ids\",selectedIds)\n694:                     .put(\"unknown_mapping_count\",history.unknown)\n695:                     .put(\"mapping_basis\",\"live confirmedInputs; current State/ModelAction object links and node Name\")\n696:                     .put(\"context_recoverable\",descriptors==null?control!=null:candidateDescriptor.recoverable));\n697:             }\n698:             // Only the selected history witnesses receive the expensive rich JSON form."}]},{"path":"native/src/com/android/commands/monkey/MonkeySourceApe.java","sha256":"200f76ef08f336dd0e70daeee6829d5f55e86d77a03775c9c7bfe6e31e9165ae","excerpts":[{"start":490,"end":515,"text":"490:             break;\n491:         case EVENT_CLEAN_RESTART:\n492:             restartPackage(((StartAction) action).getActivity(), true, \"start action\");\n493:             break;\n494:         case EVENT_NOP:\n495:             generateThrottleEvent(action.getThrottle());\n496:             break;\n497:         case EVENT_ACTIVATE:\n498:             generateActivateEvent();\n499:             break;\n500:         case MODEL_BACK:\n501:             generateKeyBackEvent();\n502:             break;\n503:         case MODEL_CLICK:\n504:             GUITreeNode node = action.getResolvedNode();\n505:             generateClickEventAt(action.getResolvedNode().getBoundsInScreen(), CLICK_WAIT_TIME);\n506:             if (node != null && node.getInputText() != null) {\n507:                 generateThrottleEvent(200); // Let the click event to be scheduled\n508:                 doInput(action, node);\n509:             }\n510:             break;\n511:         case MODEL_LONG_CLICK:\n512:             generateClickEventAt(action.getResolvedNode().getBoundsInScreen(), LONG_CLICK_WAIT_TIME);\n513:             break;\n514:         case MODEL_SCROLL_BOTTOM_UP:\n515:         case MODEL_SCROLL_TOP_DOWN:"}]},{"path":"native/src/com/android/commands/monkey/MonkeySourceApeInput.java","sha256":"f4f9f8cf2bf91d8c872ead794e0775f91531d79a67b5a5f8f51c37c7b44e58e4","excerpts":[{"start":75,"end":100,"text":"75: \n76:     private static float lerp(float a, float b, float alpha) {\n77:         return (b - a) * alpha + a;\n78:     }\n79: \n80:     void doInput(MonkeySourceApe source, Action action, GUITreeNode node) {\n81:         if (lastInputTimestamp == source.getAgent().getTimestamp()) {\n82:             Logger.wprintln(\"checkVirtualKeyboard: Input only once.\");\n83:         } else {\n84:             lastInputTimestamp = source.getAgent().getTimestamp();\n85:         }\n86:         String inputText = node.getInputText();\n87:         if (inputText != null) {\n88:             Logger.iprintln(\"Input text is \" + inputText);\n89:             generateClearEvent(source, node);\n90:             boolean sent = AndroidDevice.sendText(inputText);\n91:             if (source.getAgent() instanceof com.android.commands.monkey.ape.agent.StatefulAgent)\n92:                 ((com.android.commands.monkey.ape.agent.StatefulAgent) source.getAgent()).jevDirectTextInput(action, inputText, sent);\n93:             if (!sent) {\n94:                 attemptToSendTextByKeyEvents(source, inputText);\n95:             }\n96:         } else if (node.isEditText() || AndroidDevice.isVirtualKeyboardOpened()) {\n97:             source.generateKeyEvent(KeyEvent.KEYCODE_ESCAPE);\n98:         }\n99:     }\n100: "},{"start":125,"end":150,"text":"125:         String fullText = info.getText().toString();\n126:         if (fullText.isEmpty()) {\n127:             return 0;\n128:         }\n129:         return fullText.split(System.lineSeparator()).length;\n130:     }\n131: \n132:     private void attemptToSendTextByKeyEvents(MonkeySourceApe source, String inputText) {\n133:         char[] chars = inputText.toCharArray();\n134:         char[] one = new char[1];\n135:         for (int i = 0; i < chars.length; i++) {\n136:             one[0] = chars[i];\n137:             if (MonkeySourceApe.CharMap.getEvents(one) == null) {\n138:                 chars[i] = ' ';\n139:             }\n140:         }\n141:         KeyEvent[] events = MonkeySourceApe.CharMap.getEvents(chars);\n142:         for (int i = 0; i < events.length; i++) {\n143:             source.addEvent(new MonkeyKeyEvent(events[i]));\n144:         }\n145:         source.generateKeyEvent(KeyEvent.KEYCODE_ENTER);\n146:         source.generateThrottleEvent(200);\n147:     }\n148: }"}]}]
