1 /*
2  * Copyright (C) 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 android.server.wm.insets;
18 
19 import static android.graphics.Insets.NONE;
20 import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE;
21 import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP;
22 
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertNull;
25 import static org.junit.Assert.assertSame;
26 
27 import android.content.Context;
28 import android.graphics.Insets;
29 import android.platform.test.annotations.Presubmit;
30 import android.view.View;
31 import android.view.ViewGroup;
32 import android.view.WindowInsets;
33 import android.view.WindowInsetsAnimation;
34 import android.view.WindowInsetsAnimation.Bounds;
35 import android.widget.FrameLayout;
36 
37 import androidx.annotation.NonNull;
38 import androidx.test.platform.app.InstrumentationRegistry;
39 
40 import org.junit.Before;
41 import org.junit.Test;
42 
43 import java.util.Collections;
44 import java.util.List;
45 
46 @Presubmit
47 @android.server.wm.annotation.Group2
48 public class WindowInsetsAnimationCallbackTests {
49 
50     private static final Bounds BOUNDS = new Bounds(NONE, Insets.of(1000, 2000, 3000, 4000));
51     private static final WindowInsetsAnimation ANIMATION = new WindowInsetsAnimation(1, null, 1000);
52     private static final WindowInsets INSETS = new WindowInsets.Builder()
53             .setSystemWindowInsets(BOUNDS.getUpperBound()).build();
54     private static final List<WindowInsetsAnimation> RUNNING = Collections.singletonList(ANIMATION);
55 
56     final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
57 
58     private ViewGroup mRoot;
59     private ViewGroup mBlocking;
60     private ViewGroup mSibling;
61     private View mChild;
62     private RecordingCallback mRootCallback;
63     private RecordingCallback mBlockingCallback;
64     private RecordingCallback mSiblingCallback;
65     private RecordingCallback mChildCallback;
66 
67     @Before
setUp()68     public void setUp() throws Exception {
69         mRoot = new FrameLayout(mContext);
70         mBlocking = new FrameLayout(mContext);
71         mSibling = new FrameLayout(mContext);
72         mChild = new View(mContext);
73         mRoot.addView(mBlocking);
74         mRoot.addView(mSibling);
75         mBlocking.addView(mChild);
76 
77         mRootCallback = new RecordingCallback(DISPATCH_MODE_CONTINUE_ON_SUBTREE);
78         mBlockingCallback = new RecordingCallback(DISPATCH_MODE_STOP);
79         mSiblingCallback = new RecordingCallback(DISPATCH_MODE_STOP);
80         mChildCallback = new RecordingCallback(DISPATCH_MODE_CONTINUE_ON_SUBTREE);
81 
82         mRoot.setWindowInsetsAnimationCallback(mRootCallback);
83         mBlocking.setWindowInsetsAnimationCallback(mBlockingCallback);
84         mSibling.setWindowInsetsAnimationCallback(mSiblingCallback);
85         mChild.setWindowInsetsAnimationCallback(mChildCallback);
86     }
87 
88     @Test
dispatchWindowInsetsAnimationPrepare()89     public void dispatchWindowInsetsAnimationPrepare() {
90         mRoot.dispatchWindowInsetsAnimationPrepare(ANIMATION);
91         assertSame(ANIMATION, mRootCallback.mOnPrepare);
92         assertSame(ANIMATION, mBlockingCallback.mOnPrepare);
93         assertSame(ANIMATION, mSiblingCallback.mOnPrepare);
94         assertNull(mChildCallback.mOnPrepare);
95     }
96 
97     @Test
dispatchWindowInsetsAnimationStart()98     public void dispatchWindowInsetsAnimationStart() {
99         mRoot.dispatchWindowInsetsAnimationStart(ANIMATION, BOUNDS);
100         assertSame(ANIMATION, mRootCallback.mOnStart);
101         assertSame(ANIMATION, mBlockingCallback.mOnStart);
102         assertSame(ANIMATION, mSiblingCallback.mOnStart);
103         assertNull(mChildCallback.mOnStart);
104 
105         assertSame(BOUNDS, mRootCallback.mOnStartBoundsIn);
106         assertSame(mRootCallback.mOnStartBoundsOut, mBlockingCallback.mOnStartBoundsIn);
107         assertSame(mRootCallback.mOnStartBoundsOut, mSiblingCallback.mOnStartBoundsIn);
108     }
109 
110     @Test
dispatchWindowInsetsAnimationProgress()111     public void dispatchWindowInsetsAnimationProgress() {
112         mRoot.dispatchWindowInsetsAnimationProgress(INSETS, RUNNING);
113         assertSame(RUNNING, mRootCallback.mOnProgress);
114         assertSame(RUNNING, mBlockingCallback.mOnProgress);
115         assertSame(RUNNING, mSiblingCallback.mOnProgress);
116         assertNull(mChildCallback.mOnProgress);
117 
118         assertSame(INSETS, mRootCallback.mOnProgressIn);
119         assertSame(mRootCallback.mOnProgressOut, mBlockingCallback.mOnProgressIn);
120         assertSame(mRootCallback.mOnProgressOut, mSiblingCallback.mOnProgressIn);
121     }
122 
123     @Test
dispatchWindowInsetsAnimationEnd()124     public void dispatchWindowInsetsAnimationEnd() {
125         mRoot.dispatchWindowInsetsAnimationEnd(ANIMATION);
126         assertSame(ANIMATION, mRootCallback.mOnEnd);
127         assertSame(ANIMATION, mBlockingCallback.mOnEnd);
128         assertSame(ANIMATION, mSiblingCallback.mOnEnd);
129         assertNull(mChildCallback.mOnEnd);
130     }
131 
132     @Test
getDispatchMode()133     public void getDispatchMode() {
134         assertEquals(DISPATCH_MODE_STOP,
135                 new RecordingCallback(DISPATCH_MODE_STOP).getDispatchMode());
136         assertEquals(DISPATCH_MODE_CONTINUE_ON_SUBTREE,
137                 new RecordingCallback(DISPATCH_MODE_CONTINUE_ON_SUBTREE).getDispatchMode());
138     }
139 
140     public static class RecordingCallback extends WindowInsetsAnimation.Callback {
141 
142         WindowInsetsAnimation mOnPrepare;
143         WindowInsetsAnimation mOnStart;
144         Bounds mOnStartBoundsIn;
145         Bounds mOnStartBoundsOut;
146         WindowInsetsAnimation mOnEnd;
147         WindowInsets mOnProgressIn;
148         WindowInsets mOnProgressOut;
149         List<WindowInsetsAnimation> mOnProgress;
150 
RecordingCallback(int dispatchMode)151         public RecordingCallback(int dispatchMode) {
152             super(dispatchMode);
153         }
154 
155         @Override
onPrepare(@onNull WindowInsetsAnimation animation)156         public void onPrepare(@NonNull WindowInsetsAnimation animation) {
157             mOnPrepare = animation;
158         }
159 
160         @NonNull
161         @Override
onStart(@onNull WindowInsetsAnimation animation, @NonNull Bounds bounds)162         public Bounds onStart(@NonNull WindowInsetsAnimation animation, @NonNull Bounds bounds) {
163             mOnStart = animation;
164             mOnStartBoundsIn = bounds;
165             return mOnStartBoundsOut = bounds.inset(Insets.of(1, 2, 3, 4));
166         }
167 
168         @NonNull
169         @Override
onProgress(@onNull WindowInsets insets, @NonNull List<WindowInsetsAnimation> runningAnimations)170         public WindowInsets onProgress(@NonNull WindowInsets insets,
171                 @NonNull List<WindowInsetsAnimation> runningAnimations) {
172             mOnProgress = runningAnimations;
173             mOnProgressIn = insets;
174             return mOnProgressOut = insets.inset(1, 2, 3, 4);
175         }
176 
177         @Override
onEnd(@onNull WindowInsetsAnimation animation)178         public void onEnd(@NonNull WindowInsetsAnimation animation) {
179             mOnEnd = animation;
180         }
181     }
182 }
183