1 /* 2 * Copyright (C) 2008 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.widget.cts; 18 19 import static org.junit.Assert.assertFalse; 20 import static org.junit.Assert.assertNotNull; 21 import static org.junit.Assert.assertTrue; 22 23 import android.Manifest; 24 import android.app.Activity; 25 import android.app.Instrumentation; 26 import android.util.AttributeSet; 27 import android.util.Xml; 28 import android.view.View; 29 import android.view.ViewConfiguration; 30 import android.widget.ListView; 31 import android.widget.ZoomButton; 32 33 import androidx.test.InstrumentationRegistry; 34 import androidx.test.annotation.UiThreadTest; 35 import androidx.test.filters.LargeTest; 36 import androidx.test.filters.SmallTest; 37 import androidx.test.rule.ActivityTestRule; 38 import androidx.test.runner.AndroidJUnit4; 39 40 import com.android.compatibility.common.util.AdoptShellPermissionsRule; 41 import com.android.compatibility.common.util.CtsTouchUtils; 42 43 import org.junit.Before; 44 import org.junit.Rule; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 import org.xmlpull.v1.XmlPullParser; 48 49 import java.util.concurrent.CountDownLatch; 50 import java.util.concurrent.TimeUnit; 51 52 @SmallTest 53 @RunWith(AndroidJUnit4.class) 54 public class ZoomButtonTest { 55 private static long NANOS_IN_MILLI = 1000000; 56 57 private Instrumentation mInstrumentation; 58 private CtsTouchUtils mCtsTouchUtils; 59 private ZoomButton mZoomButton; 60 private Activity mActivity; 61 62 @Rule(order = 0) 63 public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule( 64 androidx.test.platform.app.InstrumentationRegistry 65 .getInstrumentation().getUiAutomation(), 66 Manifest.permission.START_ACTIVITIES_FROM_SDK_SANDBOX); 67 68 @Rule(order = 1) 69 public ActivityTestRule<ZoomButtonCtsActivity> mActivityRule = 70 new ActivityTestRule<>(ZoomButtonCtsActivity.class); 71 72 @Before setup()73 public void setup() { 74 mInstrumentation = InstrumentationRegistry.getInstrumentation(); 75 mCtsTouchUtils = new CtsTouchUtils(mInstrumentation.getTargetContext()); 76 mActivity = mActivityRule.getActivity(); 77 mZoomButton = (ZoomButton) mActivity.findViewById(R.id.zoombutton_test); 78 } 79 80 @UiThreadTest 81 @Test testConstructor()82 public void testConstructor() { 83 new ZoomButton(mActivity); 84 85 new ZoomButton(mActivity, null); 86 87 new ZoomButton(mActivity, null, android.R.attr.imageButtonStyle); 88 89 new ZoomButton(mActivity, null, 0, android.R.style.Widget_Material_Light_ImageButton); 90 91 XmlPullParser parser = mActivity.getResources().getXml(R.layout.zoombutton_layout); 92 AttributeSet attrs = Xml.asAttributeSet(parser); 93 assertNotNull(attrs); 94 new ZoomButton(mActivity, attrs); 95 new ZoomButton(mActivity, attrs, 0); 96 } 97 98 @Test(expected=NullPointerException.class) testConstructorWithNullContext1()99 public void testConstructorWithNullContext1() { 100 new ZoomButton(null); 101 } 102 103 @Test(expected=NullPointerException.class) testConstructorWithNullContext2()104 public void testConstructorWithNullContext2() { 105 new ZoomButton(null, null); 106 } 107 108 @Test(expected=NullPointerException.class) testConstructorWithNullContext3()109 public void testConstructorWithNullContext3() { 110 new ZoomButton(null, null, 0); 111 } 112 113 @UiThreadTest 114 @Test testSetEnabled()115 public void testSetEnabled() { 116 assertFalse(mZoomButton.isPressed()); 117 mZoomButton.setEnabled(true); 118 assertTrue(mZoomButton.isEnabled()); 119 assertFalse(mZoomButton.isPressed()); 120 121 mZoomButton.setPressed(true); 122 assertTrue(mZoomButton.isPressed()); 123 mZoomButton.setEnabled(true); 124 assertTrue(mZoomButton.isEnabled()); 125 assertTrue(mZoomButton.isPressed()); 126 127 mZoomButton.setEnabled(false); 128 assertFalse(mZoomButton.isEnabled()); 129 assertFalse(mZoomButton.isPressed()); 130 } 131 132 @UiThreadTest 133 @Test testDispatchUnhandledMove()134 public void testDispatchUnhandledMove() { 135 assertFalse(mZoomButton.dispatchUnhandledMove(new ListView(mActivity), View.FOCUS_DOWN)); 136 137 assertFalse(mZoomButton.dispatchUnhandledMove(null, View.FOCUS_DOWN)); 138 } 139 140 @LargeTest 141 @Test testSetZoomSpeed()142 public void testSetZoomSpeed() throws Throwable { 143 final long[] zoomSpeeds = { 0, 100 }; 144 mZoomButton.setEnabled(true); 145 ZoomClickListener zoomClickListener = new ZoomClickListener(); 146 mZoomButton.setOnClickListener(zoomClickListener); 147 final ZoomLongClickListener longClickListener = new ZoomLongClickListener(); 148 mZoomButton.setOnLongClickListener(longClickListener); 149 150 for (long zoomSpeed : zoomSpeeds) { 151 // Reset the tracking state of our listener, but continue using it for testing 152 // various zoom speeds on the same ZoomButton 153 zoomClickListener.reset(); 154 155 mZoomButton.setZoomSpeed(zoomSpeed); 156 157 final long startTime = System.nanoTime(); 158 // Emulate long click 159 long longPressWait = ViewConfiguration.getLongPressTimeout() + zoomSpeed + 200; 160 mCtsTouchUtils.emulateLongPressOnViewCenter(mInstrumentation, mActivityRule, 161 mZoomButton, longPressWait); 162 163 final Long callbackFirstInvocationTime = zoomClickListener.getTimeOfFirstClick(); 164 assertNotNull("Expecting at least one callback", callbackFirstInvocationTime); 165 166 // Verify that the first callback is fired after the system-level long press timeout. 167 final long minTimeUntilFirstInvocationMs = ViewConfiguration.getLongPressTimeout(); 168 final long actualTimeUntilFirstInvocationNs = callbackFirstInvocationTime - startTime; 169 assertTrue("First callback not during long press timeout was " 170 + actualTimeUntilFirstInvocationNs / NANOS_IN_MILLI 171 + " while long press timeout is " + minTimeUntilFirstInvocationMs, 172 actualTimeUntilFirstInvocationNs 173 > minTimeUntilFirstInvocationMs * NANOS_IN_MILLI); 174 assertTrue(longClickListener.postLatch.await(1, TimeUnit.SECONDS)); 175 assertTrue("First callback should have happened sooner than " 176 + actualTimeUntilFirstInvocationNs / NANOS_IN_MILLI, 177 actualTimeUntilFirstInvocationNs 178 <= longClickListener.postAfterLongClick); 179 } 180 } 181 182 private static class ZoomLongClickListener implements View.OnLongClickListener, Runnable { 183 public long postAfterLongClick; 184 public CountDownLatch postLatch; 185 186 @Override onLongClick(View v)187 public boolean onLongClick(View v) { 188 postLatch = new CountDownLatch(1); 189 v.post(this); 190 return false; 191 } 192 193 @Override run()194 public void run() { 195 postAfterLongClick = System.nanoTime(); 196 postLatch.countDown(); 197 } 198 } 199 200 private static class ZoomClickListener implements View.OnClickListener { 201 private Long mTimeOfFirstClick = null; 202 reset()203 public void reset() { 204 mTimeOfFirstClick = null; 205 } 206 getTimeOfFirstClick()207 public Long getTimeOfFirstClick() { 208 return mTimeOfFirstClick; 209 } 210 onClick(View v)211 public void onClick(View v) { 212 if (mTimeOfFirstClick == null) { 213 // Mark the current system time as the time of first click 214 mTimeOfFirstClick = System.nanoTime(); 215 } 216 } 217 } 218 } 219