1 /* 2 * Copyright (C) 2021 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 android.server.wm.jetpack.utils; 18 19 import android.app.Activity; 20 import android.content.res.Configuration; 21 import android.os.Bundle; 22 import android.view.View; 23 24 import androidx.annotation.NonNull; 25 import androidx.annotation.Nullable; 26 27 import java.util.concurrent.CountDownLatch; 28 import java.util.concurrent.TimeUnit; 29 30 /** 31 * Test activity that can verify whether the layout changes. Copied from 32 * androidx.window.TestActivity. 33 */ 34 public class TestActivity extends Activity implements View.OnLayoutChangeListener { 35 private CountDownLatch mLayoutLatch; 36 private CountDownLatch mOnConfigurationChangeLatch = new CountDownLatch(1); 37 private CountDownLatch mFocusLatch = new CountDownLatch(1); 38 private static CountDownLatch sResumeLatch = new CountDownLatch(1); 39 40 @Override onCreate(@ullable Bundle savedInstanceState)41 public void onCreate(@Nullable Bundle savedInstanceState) { 42 super.onCreate(savedInstanceState); 43 44 resetLayoutCounter(); 45 getWindow().getDecorView().addOnLayoutChangeListener(this); 46 } 47 48 @Override onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)49 public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, 50 int oldTop, int oldRight, int oldBottom) { 51 mLayoutLatch.countDown(); 52 } 53 54 @Override onConfigurationChanged(@onNull Configuration newConfig)55 public void onConfigurationChanged(@NonNull Configuration newConfig) { 56 super.onConfigurationChanged(newConfig); 57 mOnConfigurationChangeLatch.countDown(); 58 } 59 60 @Override onWindowFocusChanged(boolean hasWindowFocus)61 public void onWindowFocusChanged(boolean hasWindowFocus) { 62 if (hasWindowFocus) { 63 mFocusLatch.countDown(); 64 } 65 } 66 67 @Override onResume()68 protected void onResume() { 69 super.onResume(); 70 sResumeLatch.countDown(); 71 } 72 73 /** 74 * Resets layout counter when waiting for a layout to happen before calling 75 * {@link #waitForLayout()}. 76 */ resetLayoutCounter()77 public void resetLayoutCounter() { 78 mLayoutLatch = new CountDownLatch(1); 79 } 80 81 /** 82 * Blocks and waits for the next layout to happen. {@link #resetLayoutCounter()} must be called 83 * before calling this method. 84 * @return {@code true} if the layout happened before the timeout count reached zero and 85 * {@code false} if the waiting time elapsed before the layout happened. 86 */ waitForLayout()87 public boolean waitForLayout() { 88 try { 89 return mLayoutLatch.await(3, TimeUnit.SECONDS); 90 } catch (InterruptedException e) { 91 return false; 92 } 93 } 94 95 /** 96 * Resets the focus counter. 97 */ resetFocusCounter()98 public void resetFocusCounter() { 99 mFocusLatch = new CountDownLatch(1); 100 } 101 102 /** 103 * Waits for receiving the first window focus. 104 * 105 * @return {@code true} if the window ever becomes the focused window. 106 */ waitForFocus()107 public boolean waitForFocus() { 108 try { 109 return mFocusLatch.await(3, TimeUnit.SECONDS); 110 } catch (InterruptedException e) { 111 return false; 112 } 113 } 114 115 /** 116 * Resets the configuration change counter. 117 */ resetOnConfigurationChangeCounter()118 public void resetOnConfigurationChangeCounter() { 119 mOnConfigurationChangeLatch = new CountDownLatch(1); 120 } 121 122 /** 123 * Waits for a configuration change callback. 124 * 125 * @return {@code true} if the configuration change callback is triggered, {@code false} 126 * otherwise. 127 */ waitForConfigurationChange()128 public boolean waitForConfigurationChange() { 129 try { 130 return mOnConfigurationChangeLatch.await(3, TimeUnit.SECONDS); 131 } catch (InterruptedException e) { 132 return false; 133 } 134 } 135 136 /** 137 * Resets layout counter when waiting for a layout to happen before calling 138 * {@link #waitForOnResume()}. 139 */ resetResumeCounter()140 public static void resetResumeCounter() { 141 sResumeLatch = new CountDownLatch(1); 142 } 143 144 /** 145 * Same as {@link #waitForLayout()}, but waits for onResume() to be called for any activity of 146 * this class. This can be used to track activity re-creation. 147 * @return {@code true} if the onResume() happened before the timeout count reached zero and 148 * {@code false} if the waiting time elapsed before the onResume() happened. 149 */ waitForOnResume()150 public static boolean waitForOnResume() { 151 try { 152 return sResumeLatch.await(3, TimeUnit.SECONDS); 153 } catch (InterruptedException e) { 154 return false; 155 } 156 } 157 } 158