1 /*
2  * Copyright (C) 2018 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.graphics.drawable.cts;
18 
19 import static junit.framework.TestCase.assertTrue;
20 
21 import static org.junit.Assert.assertEquals;
22 
23 import android.graphics.drawable.Animatable2;
24 import android.graphics.drawable.Drawable;
25 import android.os.Looper;
26 
27 // Now this class can not only listen to the events, but also synchronize the key events,
28 // logging the event timestamp, and centralize some assertions.
29 public class Animatable2Callback extends Animatable2.AnimationCallback {
30     private static final long MAX_START_TIMEOUT_MS = 5000;
31 
32     private boolean mStarted = false;
33     private Thread mStartThread;
34     private boolean mEnded = false;
35     private Thread mEndThread;
36 
37     private long mStartNs = Long.MAX_VALUE;
38     private long mEndNs = Long.MIN_VALUE;
39 
40     // Use this lock to make sure the onAnimationEnd() has been called.
41     // Each sub test should have its own lock.
42     private final Object mEndLock = new Object();
43 
44     // Use this lock to make sure the test thread know when the AVD.start() has been called.
45     // Each sub test should have its own lock.
46     private final Object mStartLock = new Object();
47 
waitForEnd(long timeoutMs)48     public boolean waitForEnd(long timeoutMs) throws InterruptedException {
49         synchronized (mEndLock) {
50             if (!mEnded) {
51                 // Return immediately if the AVD has already ended.
52                 mEndLock.wait(timeoutMs);
53             }
54             return mEnded;
55         }
56     }
57 
waitForStart()58     public boolean waitForStart() throws InterruptedException {
59         synchronized(mStartLock) {
60             if (!mStarted) {
61                 // Return immediately if the AVD has already started.
62                 mStartLock.wait(MAX_START_TIMEOUT_MS);
63             }
64             return mStarted;
65         }
66     }
67 
68     @Override
onAnimationStart(Drawable drawable)69     public void onAnimationStart(Drawable drawable) {
70         mStartNs = System.nanoTime();
71         mStartThread = Thread.currentThread();
72         synchronized(mStartLock) {
73             mStarted = true;
74             mStartLock.notify();
75         }
76     }
77 
78     @Override
onAnimationEnd(Drawable drawable)79     public void onAnimationEnd(Drawable drawable) {
80         mEndNs = System.nanoTime();
81         mEndThread = Thread.currentThread();
82         synchronized (mEndLock) {
83             mEnded = true;
84             mEndLock.notify();
85         }
86     }
87 
endIsCalled()88     public boolean endIsCalled() {
89         synchronized (mEndLock) {
90             return mEnded;
91         }
92     }
93 
assertStarted(boolean started)94     public void assertStarted(boolean started) {
95         assertEquals(started, mStarted);
96         if (started) {
97             assertEquals("onAnimationStart happened on wrong thread",
98                     Looper.getMainLooper().getThread(), mStartThread);
99         }
100     }
101 
assertEnded(boolean ended)102     public void assertEnded(boolean ended) {
103         assertEquals(ended, mEnded);
104         if (ended) {
105             assertEquals("onAnimationEnd happened on wrong thread",
106                     Looper.getMainLooper().getThread(), mEndThread);
107         }
108     }
109 
assertAVDRuntime(long min, long max)110     public void assertAVDRuntime(long min, long max) {
111         assertTrue(mStartNs != Long.MAX_VALUE);
112         assertTrue(mEndNs != Long.MIN_VALUE);
113         long durationNs = mEndNs - mStartNs;
114         assertTrue("current duration " + durationNs + " should be within " +
115                    min + "," + max, durationNs <= max && durationNs >= min);
116         assertEquals("onAnimationStart happened on wrong thread",
117                 Looper.getMainLooper().getThread(), mStartThread);
118         assertEquals("onAnimationEnd happened on wrong thread",
119                 Looper.getMainLooper().getThread(), mEndThread);
120     }
121 }
122