1 package android.server.am.lifecycle; 2 3 import static android.server.am.StateLogger.log; 4 import static android.support.test.runner.lifecycle.Stage.CREATED; 5 import static android.support.test.runner.lifecycle.Stage.DESTROYED; 6 import static android.support.test.runner.lifecycle.Stage.PAUSED; 7 import static android.support.test.runner.lifecycle.Stage.PRE_ON_CREATE; 8 import static android.support.test.runner.lifecycle.Stage.RESUMED; 9 import static android.support.test.runner.lifecycle.Stage.STARTED; 10 import static android.support.test.runner.lifecycle.Stage.STOPPED; 11 12 import android.app.Activity; 13 import android.support.test.runner.lifecycle.ActivityLifecycleCallback; 14 import android.support.test.runner.lifecycle.Stage; 15 import android.util.Pair; 16 17 import java.util.ArrayList; 18 import java.util.List; 19 20 /** 21 * Used as a shared log storage of activity lifecycle transitions. Methods must be synchronized to 22 * prevent concurrent modification of the log store. 23 */ 24 class LifecycleLog implements ActivityLifecycleCallback { 25 26 enum ActivityCallback { 27 PRE_ON_CREATE, 28 ON_CREATE, 29 ON_START, 30 ON_RESUME, 31 ON_PAUSE, 32 ON_STOP, 33 ON_RESTART, 34 ON_DESTROY, 35 ON_ACTIVITY_RESULT, 36 ON_POST_CREATE, 37 ON_NEW_INTENT, 38 ON_MULTI_WINDOW_MODE_CHANGED 39 } 40 41 /** 42 * Log for encountered activity callbacks. Note that methods accessing or modifying this 43 * list should be synchronized as it can be accessed from different threads. 44 */ 45 private List<Pair<String, ActivityCallback>> mLog = new ArrayList<>(); 46 47 /** Clear the entire transition log. */ 48 synchronized void clear() { 49 mLog.clear(); 50 } 51 52 /** Add transition of an activity to the log. */ 53 @Override 54 synchronized public void onActivityLifecycleChanged(Activity activity, Stage stage) { 55 final String activityName = activity.getClass().getCanonicalName(); 56 log("Activity " + activityName + " moved to stage " + stage); 57 mLog.add(new Pair<>(activityName, stageToCallback(stage))); 58 } 59 60 /** Add activity callback to the log. */ 61 synchronized public void onActivityCallback(Activity activity, ActivityCallback callback) { 62 final String activityName = activity.getClass().getCanonicalName(); 63 log("Activity " + activityName + " got a callback " + callback); 64 mLog.add(new Pair<>(activityName, callback)); 65 } 66 67 /** Get logs for all recorded transitions. */ 68 synchronized List<Pair<String, ActivityCallback>> getLog() { 69 // Wrap in a new list to prevent concurrent modification 70 return new ArrayList<>(mLog); 71 } 72 73 /** Get transition logs for the specified activity. */ 74 synchronized List<ActivityCallback> getActivityLog(Class<? extends Activity> activityClass) { 75 final String activityName = activityClass.getCanonicalName(); 76 log("Looking up log for activity: " + activityName); 77 final List<ActivityCallback> activityLog = new ArrayList<>(); 78 for (Pair<String, ActivityCallback> transition : mLog) { 79 if (transition.first.equals(activityName)) { 80 activityLog.add(transition.second); 81 } 82 } 83 return activityLog; 84 } 85 86 private static ActivityCallback stageToCallback(Stage stage) { 87 switch (stage) { 88 case PRE_ON_CREATE: 89 return ActivityCallback.PRE_ON_CREATE; 90 case CREATED: 91 return ActivityCallback.ON_CREATE; 92 case STARTED: 93 return ActivityCallback.ON_START; 94 case RESUMED: 95 return ActivityCallback.ON_RESUME; 96 case PAUSED: 97 return ActivityCallback.ON_PAUSE; 98 case STOPPED: 99 return ActivityCallback.ON_STOP; 100 case RESTARTED: 101 return ActivityCallback.ON_RESTART; 102 case DESTROYED: 103 return ActivityCallback.ON_DESTROY; 104 default: 105 throw new IllegalArgumentException("Unsupported stage: " + stage); 106 } 107 } 108 } 109