1 /* 2 * Copyright 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.car.app.testing; 18 19 import static java.util.Objects.requireNonNull; 20 21 import android.content.Intent; 22 23 import androidx.car.app.Session; 24 import androidx.lifecycle.DefaultLifecycleObserver; 25 import androidx.lifecycle.Lifecycle; 26 import androidx.lifecycle.Lifecycle.Event; 27 import androidx.lifecycle.LifecycleOwner; 28 import androidx.lifecycle.LifecycleRegistry; 29 30 import org.jspecify.annotations.NonNull; 31 32 /** 33 * {@link SessionController} provides API that allows testing of a {@link Session}. 34 * 35 * <p>This controller allows: 36 * 37 * <ul> 38 * <li>Injecting a {@link TestCarContext} into the {@link Session} instance, which provides access 39 * to the test managers and other testing functionalities. 40 * </ul> 41 */ 42 public class SessionController { 43 final Session mSession; 44 final TestCarContext mTestCarContext; 45 final Intent mIntent; 46 private final TestLifecycleOwner mLifecycleOwner; 47 48 /** 49 * Creates a {@link SessionController} to control the provided {@link Session}. 50 * 51 * @param session the {@link Session} to control 52 * @param context the {@link TestCarContext} that the {@code session} should use. 53 * @param intent the {@link Intent} that the {@code session} should start with during the 54 * {@link androidx.lifecycle.Lifecycle.State#CREATED} state. 55 * @throws NullPointerException if {@code session} or {@code context} is {@code null} 56 */ SessionController(@onNull Session session, @NonNull TestCarContext context, @NonNull Intent intent)57 public SessionController(@NonNull Session session, @NonNull TestCarContext context, 58 @NonNull Intent intent) { 59 mSession = requireNonNull(session); 60 mTestCarContext = requireNonNull(context); 61 mIntent = requireNonNull(intent); 62 63 mLifecycleOwner = new TestLifecycleOwner(); 64 mLifecycleOwner.getRegistry().addObserver(new SessionLifecycleObserver()); 65 66 mSession.setCarContextInternal(mTestCarContext); 67 mSession.setLifecycleRegistryInternal(mTestCarContext.getLifecycleOwner().getRegistry()); 68 } 69 70 /** Returns the {@link Session} that is being controlled. */ getSession()71 public @NonNull Session getSession() { 72 return mSession; 73 } 74 75 /** 76 * Moves the {@link Session} being controlled to the input {@code state}. 77 * 78 * <p>Note that {@link Lifecycle.State#DESTROYED} is a terminal state, and you cannot move to 79 * any other state after the {@link Session} reaches that state.</p> 80 * 81 * @see Session#getLifecycle 82 */ moveToState(Lifecycle.@onNull State state)83 public @NonNull SessionController moveToState(Lifecycle.@NonNull State state) { 84 mLifecycleOwner.getRegistry().setCurrentState(state); 85 return this; 86 } 87 88 /** 89 * A helper class to forward the lifecycle events from this controller to the session. 90 */ 91 class SessionLifecycleObserver implements DefaultLifecycleObserver { 92 @Override onCreate(@onNull LifecycleOwner owner)93 public void onCreate(@NonNull LifecycleOwner owner) { 94 LifecycleRegistry registry = (LifecycleRegistry) mSession.getLifecycle(); 95 TestScreenManager screenManager = mTestCarContext.getCarService( 96 TestScreenManager.class); 97 registry.handleLifecycleEvent(Event.ON_CREATE); 98 screenManager.push(mSession.onCreateScreen(mIntent)); 99 } 100 101 @Override onStart(@onNull LifecycleOwner owner)102 public void onStart(@NonNull LifecycleOwner owner) { 103 LifecycleRegistry registry = (LifecycleRegistry) mSession.getLifecycle(); 104 registry.handleLifecycleEvent(Event.ON_START); 105 } 106 107 @Override onResume(@onNull LifecycleOwner owner)108 public void onResume(@NonNull LifecycleOwner owner) { 109 LifecycleRegistry registry = (LifecycleRegistry) mSession.getLifecycle(); 110 registry.handleLifecycleEvent(Event.ON_RESUME); 111 } 112 113 @Override onPause(@onNull LifecycleOwner owner)114 public void onPause(@NonNull LifecycleOwner owner) { 115 LifecycleRegistry registry = (LifecycleRegistry) mSession.getLifecycle(); 116 registry.handleLifecycleEvent(Event.ON_PAUSE); 117 } 118 119 @Override onStop(@onNull LifecycleOwner owner)120 public void onStop(@NonNull LifecycleOwner owner) { 121 LifecycleRegistry registry = (LifecycleRegistry) mSession.getLifecycle(); 122 registry.handleLifecycleEvent(Event.ON_STOP); 123 } 124 125 @Override onDestroy(@onNull LifecycleOwner owner)126 public void onDestroy(@NonNull LifecycleOwner owner) { 127 LifecycleRegistry registry = (LifecycleRegistry) mSession.getLifecycle(); 128 registry.handleLifecycleEvent(Event.ON_DESTROY); 129 } 130 } 131 } 132