1 // Copyright 2023 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.base.test.transit; 6 7 import androidx.annotation.Nullable; 8 9 import org.chromium.base.Log; 10 11 import java.util.ArrayList; 12 13 /** 14 * A {@link Transition} into a {@link TransitStation}, either from another TransitStation or as an 15 * entry point. 16 */ 17 public class Trip extends Transition { 18 private static final String TAG = "Transit"; 19 private final int mId; 20 21 @Nullable private final TransitStation mOrigin; 22 private final TransitStation mDestination; 23 24 private static int sLastTripId; 25 Trip(@ullable TransitStation origin, TransitStation destination, Trigger trigger)26 private Trip(@Nullable TransitStation origin, TransitStation destination, Trigger trigger) { 27 super(trigger); 28 mOrigin = origin; 29 mDestination = destination; 30 mId = ++sLastTripId; 31 } 32 33 /** 34 * Starts a transition from a TransitStation to another (or from no TransitStation if at an 35 * entry point). Runs the transition |trigger|, and blocks until the destination TransitStation 36 * is considered ACTIVE (enter Conditions are fulfilled), the origin TransitStation is 37 * considered FINISHED (exit Conditions are fulfilled), and the Transition's conditions are 38 * fulfilled. 39 * 40 * @param origin the StationFacility to depart from, null if at an entry point. 41 * @param destination the StationFacility to arrive at. 42 * @param trigger the trigger to start the transition (e.g. clicking a view). 43 * @return the TransitStation entered. 44 * @param <T> the type of TransitStation entered. 45 */ travelSync( @ullable TransitStation origin, T destination, Trigger trigger)46 public static <T extends TransitStation> T travelSync( 47 @Nullable TransitStation origin, T destination, Trigger trigger) { 48 Trip trip = new Trip(origin, destination, trigger); 49 trip.travelSyncInternal(); 50 return destination; 51 } 52 travelSyncInternal()53 private void travelSyncInternal() { 54 embark(); 55 if (mOrigin != null) { 56 Log.i(TAG, "Trip %d: Embarked at %s towards %s", mId, mOrigin, mDestination); 57 } else { 58 Log.i(TAG, "Trip %d: Starting at entry point %s", mId, mDestination); 59 } 60 61 triggerTransition(); 62 Log.i(TAG, "Trip %d: Triggered transition, waiting to arrive at %s", mId, mDestination); 63 64 waitUntilArrival(); 65 Log.i(TAG, "Trip %d: Arrived at %s", mId, mDestination); 66 67 PublicTransitConfig.maybePauseAfterTransition(mDestination); 68 } 69 embark()70 private void embark() { 71 if (mOrigin != null) { 72 mOrigin.setStateTransitioningFrom(); 73 } 74 mDestination.setStateTransitioningTo(); 75 } 76 waitUntilArrival()77 private void waitUntilArrival() { 78 ArrayList<ConditionWaiter.ConditionWaitStatus> waitStatuses = new ArrayList<>(); 79 80 if (mOrigin != null) { 81 for (Condition condition : mOrigin.getExitConditions()) { 82 waitStatuses.add( 83 new ConditionWaiter.ConditionWaitStatus( 84 condition, ConditionWaiter.ConditionOrigin.EXIT)); 85 } 86 for (Condition condition : mOrigin.getActiveFacilityExitConditions()) { 87 waitStatuses.add( 88 new ConditionWaiter.ConditionWaitStatus( 89 condition, ConditionWaiter.ConditionOrigin.EXIT)); 90 } 91 } 92 93 for (Condition condition : mDestination.getEnterConditions()) { 94 waitStatuses.add( 95 new ConditionWaiter.ConditionWaitStatus( 96 condition, ConditionWaiter.ConditionOrigin.ENTER)); 97 } 98 for (Condition condition : getTransitionConditions()) { 99 waitStatuses.add( 100 new ConditionWaiter.ConditionWaitStatus( 101 condition, ConditionWaiter.ConditionOrigin.TRANSITION)); 102 } 103 104 // Throws CriteriaNotSatisfiedException if any conditions aren't met within the timeout and 105 // prints the state of all conditions. The timeout can be reduced when explicitly looking 106 // for flakiness due to tight timeouts. 107 try { 108 ConditionWaiter.waitFor(waitStatuses); 109 } catch (AssertionError e) { 110 throw new TravelException(mOrigin, mDestination, e); 111 } 112 113 if (mOrigin != null) { 114 mOrigin.setStateFinished(); 115 } 116 mDestination.setStateActive(); 117 TrafficControl.notifyActiveStationChanged(mDestination); 118 } 119 } 120