Merge "Fix flaky TransitionManagerTest"
diff --git a/apps/CtsVerifier/res/layout-small-dpad/widget_layout.xml b/apps/CtsVerifier/res/layout-small-dpad/widget_layout.xml
new file mode 100644
index 0000000..518be88
--- /dev/null
+++ b/apps/CtsVerifier/res/layout-small-dpad/widget_layout.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginTop="@dimen/widget_margin_top"
+ android:layout_marginBottom="@dimen/widget_margin_bottom"
+ android:layout_marginLeft="@dimen/widget_margin_left"
+ android:layout_marginRight="@dimen/widget_margin_right"
+ android:padding="1dp"
+ android:background="#fff">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingLeft="4dp"
+ android:paddingTop="4dp"
+ android:paddingBottom="4dp"
+ android:paddingRight="4dp"
+ android:layout_gravity="center"
+ android:background="#fff">
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="top|left"
+ android:layout_marginBottom="8dp"
+ android:fontFamily="sans-serif"
+ android:textSize="16sp"
+ android:text="@string/widget_name"
+ android:freezesText="true"/>
+
+ <TextView
+ android:id="@+id/instruction"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="12dp"
+ android:fontFamily="sans-serif-light"
+ android:textSize="14sp"
+ android:freezesText="true"/>
+
+ <TextView
+ android:id="@+id/data"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="12dp"
+ android:layout_gravity="center_horizontal"
+ android:fontFamily="sans-serif-light"
+ android:textSize="14sp"/>
+
+ <ListView
+ android:id="@+id/list"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:layout_marginBottom="12dp"
+ android:padding="1dp"
+ android:background="#fff"
+ android:visibility="gone"/>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|center_horizontal"
+ android:orientation="horizontal">
+ <Button
+ android:id="@+id/fail"
+ android:layout_marginRight="8dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minWidth="100dp"
+ android:text="@string/widget_fail" />
+ <Button
+ android:id="@+id/pass"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minWidth="100dp"
+ android:text="@string/widget_pass" />
+ </LinearLayout>
+
+ </LinearLayout>
+</FrameLayout>
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/SafeCleanerRule.java b/common/device-side/util/src/com/android/compatibility/common/util/SafeCleanerRule.java
index 9c218d2..806884c 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/SafeCleanerRule.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/SafeCleanerRule.java
@@ -40,7 +40,7 @@
private static final String TAG = "SafeCleanerRule";
- private final List<Runnable> mCleaners = new ArrayList<>();
+ private final List<ThrowingRunnable> mCleaners = new ArrayList<>();
private final List<Callable<List<Throwable>>> mExtraThrowables = new ArrayList<>();
private final List<Throwable> mThrowables = new ArrayList<>();
private Dumper mDumper;
@@ -48,7 +48,7 @@
/**
* Runs {@code cleaner} after the test is finished, catching any {@link Throwable} thrown by it.
*/
- public SafeCleanerRule run(@NonNull Runnable cleaner) {
+ public SafeCleanerRule run(@NonNull ThrowingRunnable cleaner) {
mCleaners.add(cleaner);
return this;
}
@@ -96,7 +96,7 @@
}
// Then the cleanup runners
- for (Runnable runner : mCleaners) {
+ for (ThrowingRunnable runner : mCleaners) {
try {
runner.run();
} catch (Throwable t) {
@@ -108,7 +108,7 @@
// And finally add the extra exceptions
for (Callable<List<Throwable>> extraThrowablesCallable : mExtraThrowables) {
final List<Throwable> extraThrowables = extraThrowablesCallable.call();
- if (extraThrowables != null) {
+ if (extraThrowables != null && !extraThrowables.isEmpty()) {
Log.w(TAG, "Adding " + extraThrowables.size() + " extra exceptions");
mThrowables.addAll(extraThrowables);
}
diff --git a/common/device-side/util/tests/src/com/android/compatibility/common/util/SafeCleanerRuleTest.java b/common/device-side/util/tests/src/com/android/compatibility/common/util/SafeCleanerRuleTest.java
index 99ea3c0..a56d7b2 100644
--- a/common/device-side/util/tests/src/com/android/compatibility/common/util/SafeCleanerRuleTest.java
+++ b/common/device-side/util/tests/src/com/android/compatibility/common/util/SafeCleanerRuleTest.java
@@ -58,8 +58,8 @@
@Mock private Dumper mDumper;
// Use mocks for objects that don't throw any exception.
- @Mock private Runnable mGoodGuyRunner1;
- @Mock private Runnable mGoodGuyRunner2;
+ @Mock private ThrowingRunnable mGoodGuyRunner1;
+ @Mock private ThrowingRunnable mGoodGuyRunner2;
@Mock private Callable<List<Throwable>> mGoodGuyExtraExceptions1;
@Mock private Callable<List<Throwable>> mGoodGuyExtraExceptions2;
@Mock private Statement mGoodGuyStatement;
@@ -261,6 +261,7 @@
final Exception extra1 = new Exception("1");
final Exception extra2 = new Exception("2");
final Exception extra3 = new Exception("3");
+ final Exception extra4 = new Exception("4");
final Error error1 = new Error("one");
final Error error2 = new Error("two");
final RuntimeException testException = new RuntimeException("TEST, Y U NO PASS?");
@@ -277,13 +278,18 @@
.run(mGoodGuyRunner2)
.add(() -> { return ImmutableList.of(extra3); })
.add(mGoodGuyExtraExceptions2)
- .run(() -> { throw error2; });
+ .run(() -> {
+ throw error2;
+ })
+ .run(() -> {
+ throw extra4;
+ });
final SafeCleanerRule.MultipleExceptions actualException = expectThrows(
SafeCleanerRule.MultipleExceptions.class,
() -> rule.apply(new FailureStatement(testException), mDescription).evaluate());
assertThat(actualException.getThrowables())
- .containsExactly(testException, error1, error2, extra1, extra2, extra3)
+ .containsExactly(testException, error1, error2, extra4, extra1, extra2, extra3)
.inOrder();
verify(mGoodGuyRunner1).run();
verify(mGoodGuyRunner2).run();
diff --git a/hostsidetests/dumpsys/AndroidTest.xml b/hostsidetests/dumpsys/AndroidTest.xml
index ead52be..11ab26f 100644
--- a/hostsidetests/dumpsys/AndroidTest.xml
+++ b/hostsidetests/dumpsys/AndroidTest.xml
@@ -18,6 +18,7 @@
<option name="config-descriptor:metadata" key="component" value="framework" />
<!-- This module tests system service dumps, which is irrelevant for Instant Apps. -->
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest">
<option name="jar" value="CtsDumpsysHostTestCases.jar" />
</test>
diff --git a/tests/app/app/src/android/app/stubs/ActivityCallbacksTestActivity.java b/tests/app/app/src/android/app/stubs/ActivityCallbacksTestActivity.java
index 38f0b52..fb0ccf2 100644
--- a/tests/app/app/src/android/app/stubs/ActivityCallbacksTestActivity.java
+++ b/tests/app/app/src/android/app/stubs/ActivityCallbacksTestActivity.java
@@ -55,10 +55,12 @@
public enum Source {
ACTIVITY,
ACTIVITY_CALLBACK,
+ ACTIVITY_CALLBACK_CREATE_ONLY,
APPLICATION_ACTIVITY_CALLBACK
}
private final Application.ActivityLifecycleCallbacks mActivityCallbacks;
+ private final Application.ActivityLifecycleCallbacks mActivityCallbacksCreateOnly;
private ArrayList<Pair<Source, Event>> mCollectedEvents = new ArrayList<>();
@@ -161,6 +163,101 @@
}
};
registerActivityLifecycleCallbacks(mActivityCallbacks);
+ mActivityCallbacksCreateOnly = new Application.ActivityLifecycleCallbacks() {
+
+ @Override
+ public void onActivityPreCreated(Activity activity, Bundle savedInstanceState) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_PRE_CREATE);
+ }
+
+ @Override
+ public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_CREATE);
+ }
+
+ @Override
+ public void onActivityPostCreated(Activity activity, Bundle savedInstanceState) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_POST_CREATE);
+ // We shouldn't get any additional callbacks after this point
+ unregisterActivityLifecycleCallbacks(this);
+ }
+
+ @Override
+ public void onActivityStarted(Activity activity) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_START);
+ }
+
+ @Override
+ public void onActivityPostStarted(Activity activity) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_POST_START);
+ }
+
+ @Override
+ public void onActivityPreResumed(Activity activity) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_PRE_RESUME);
+ }
+
+ @Override
+ public void onActivityResumed(Activity activity) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_RESUME);
+ }
+
+ @Override
+ public void onActivityPostResumed(Activity activity) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_POST_RESUME);
+ }
+
+ @Override
+ public void onActivityPrePaused(Activity activity) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_PRE_PAUSE);
+ }
+
+ @Override
+ public void onActivityPaused(Activity activity) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_PAUSE);
+ }
+
+ @Override
+ public void onActivityPostPaused(Activity activity) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_POST_PAUSE);
+ }
+
+ @Override
+ public void onActivityPreStopped(Activity activity) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_PRE_STOP);
+ }
+
+ @Override
+ public void onActivityStopped(Activity activity) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_STOP);
+ }
+
+ @Override
+ public void onActivityPostStopped(Activity activity) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_POST_STOP);
+ }
+
+ @Override
+ public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
+
+ }
+
+ @Override
+ public void onActivityPreDestroyed(Activity activity) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_PRE_DESTROY);
+ }
+
+ @Override
+ public void onActivityDestroyed(Activity activity) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_DESTROY);
+ }
+
+ @Override
+ public void onActivityPostDestroyed(Activity activity) {
+ collectEvent(Source.ACTIVITY_CALLBACK_CREATE_ONLY, Event.ON_POST_DESTROY);
+ }
+ };
+ registerActivityLifecycleCallbacks(mActivityCallbacksCreateOnly);
}
public void collectEvent(Source source, Event event) {
diff --git a/tests/app/src/android/app/cts/ActivityCallbacksTest.java b/tests/app/src/android/app/cts/ActivityCallbacksTest.java
index ff9c401..909748f 100644
--- a/tests/app/src/android/app/cts/ActivityCallbacksTest.java
+++ b/tests/app/src/android/app/cts/ActivityCallbacksTest.java
@@ -229,11 +229,19 @@
Event preEvent, Event event, Event postEvent) {
expectedEvents.add(new Pair<>(Source.APPLICATION_ACTIVITY_CALLBACK, preEvent));
expectedEvents.add(new Pair<>(Source.ACTIVITY_CALLBACK, preEvent));
+ if (preEvent == ON_PRE_CREATE) {
+ // ACTIVITY_CALLBACK_CREATE_ONLY only gets create events
+ expectedEvents.add(new Pair<>(Source.ACTIVITY_CALLBACK_CREATE_ONLY, preEvent));
+ }
expectedEvents.add(new Pair<>(Source.ACTIVITY, preEvent));
if (event == ON_CREATE || event == ON_START || event == ON_RESUME) {
// Application goes first on upward lifecycle events
expectedEvents.add(new Pair<>(Source.APPLICATION_ACTIVITY_CALLBACK, event));
expectedEvents.add(new Pair<>(Source.ACTIVITY_CALLBACK, event));
+ if (event == ON_CREATE) {
+ // ACTIVITY_CALLBACK_CREATE_ONLY only gets create events
+ expectedEvents.add(new Pair<>(Source.ACTIVITY_CALLBACK_CREATE_ONLY, event));
+ }
} else {
// Application goes last on downward lifecycle events
expectedEvents.add(new Pair<>(Source.ACTIVITY_CALLBACK, event));
@@ -241,6 +249,10 @@
}
expectedEvents.add(new Pair<>(Source.ACTIVITY, postEvent));
expectedEvents.add(new Pair<>(Source.ACTIVITY_CALLBACK, postEvent));
+ if (postEvent == ON_POST_CREATE) {
+ // ACTIVITY_CALLBACK_CREATE_ONLY only gets create events
+ expectedEvents.add(new Pair<>(Source.ACTIVITY_CALLBACK_CREATE_ONLY, postEvent));
+ }
expectedEvents.add(new Pair<>(Source.APPLICATION_ACTIVITY_CALLBACK, postEvent));
}
}
diff --git a/tests/autofillservice/AndroidTest.xml b/tests/autofillservice/AndroidTest.xml
index 4fe406f..e7413b1 100644
--- a/tests/autofillservice/AndroidTest.xml
+++ b/tests/autofillservice/AndroidTest.xml
@@ -17,6 +17,7 @@
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="autofill" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
diff --git a/tests/contentcaptureservice/AndroidTest.xml b/tests/contentcaptureservice/AndroidTest.xml
index 941df89..e974112 100644
--- a/tests/contentcaptureservice/AndroidTest.xml
+++ b/tests/contentcaptureservice/AndroidTest.xml
@@ -16,6 +16,7 @@
<configuration description="Config for ContentCapture CTS tests.">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
diff --git a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanVerification.java b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanVerification.java
index 17882d7..7a48ba8 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanVerification.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/sensorverification/MeanVerification.java
@@ -23,6 +23,7 @@
import android.hardware.cts.helpers.SensorCtsHelper;
import android.hardware.cts.helpers.SensorStats;
import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.content.pm.PackageManager;
import java.util.HashMap;
import java.util.Map;
@@ -65,13 +66,23 @@
* @return the verification or null if the verification does not apply to the sensor.
*/
public static MeanVerification getDefault(TestSensorEnvironment environment) {
+
+ Map<Integer, ExpectedValuesAndThresholds> currentDefaults =
+ new HashMap<Integer, ExpectedValuesAndThresholds>(DEFAULTS);
+
+ // For automotive flag, add car default tests.
+ if(environment.getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE)) {
+ addCarDefaultTests(currentDefaults);
+ }
+
int sensorType = environment.getSensor().getType();
- if (!DEFAULTS.containsKey(sensorType)) {
+ if (!currentDefaults.containsKey(sensorType)) {
return null;
}
- float[] expected = DEFAULTS.get(sensorType).mExpectedValues;
- float[] upperThresholds = DEFAULTS.get(sensorType).mUpperThresholds;
- float[] lowerThresholds = DEFAULTS.get(sensorType).mLowerThresholds;
+ float[] expected = currentDefaults.get(sensorType).mExpectedValues;
+ float[] upperThresholds = currentDefaults.get(sensorType).mUpperThresholds;
+ float[] lowerThresholds = currentDefaults.get(sensorType).mLowerThresholds;
return new MeanVerification(expected, upperThresholds, lowerThresholds);
}
@@ -186,6 +197,20 @@
Float.MAX_VALUE}));
}
+ @SuppressWarnings("deprecation")
+ private static void addCarDefaultTests(Map<Integer, ExpectedValuesAndThresholds> defaults) {
+ // Sensors that are being tested for mean verification for the car.
+ // Accelerometer axes should be aligned to car axes: X right, Y forward, Z up.
+ // Refer for car axes: https://source.android.com/devices/sensors/sensor-types
+ // Verifying Z axis is Gravity, X and Y is zero as car is expected to be stationary.
+ // Tolerance set to 1.95 as used in CTS Verifier tests.
+ defaults.put(Sensor.TYPE_ACCELEROMETER,
+ new ExpectedValuesAndThresholds(
+ new float[]{0.0f, 0.0f, SensorManager.STANDARD_GRAVITY},
+ new float[]{1.95f, 1.95f, 1.95f} /* m / s^2 */,
+ new float[]{1.95f, 1.95f, 1.95f} /* m / s^2 */));
+ }
+
private static final class ExpectedValuesAndThresholds {
private float[] mExpectedValues;
private float[] mUpperThresholds;
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
index 99fbff7..1b7dbf8 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -1050,6 +1050,8 @@
SystemClock.sleep(500);
}
+ mUiDevice.pressHome();
+
setUsageSourceSetting(Integer.toString(mUsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY));
launchSubActivity(TaskRootActivity.class);
// Usage should be attributed to the test app package
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecClearKeyPlayer.java b/tests/tests/media/src/android/media/cts/MediaCodecClearKeyPlayer.java
index 5b2ad2f..6aaafe5 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecClearKeyPlayer.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecClearKeyPlayer.java
@@ -115,6 +115,9 @@
" \"track_types\": [ ] " +
"} " ;
+ // ClearKey private data (0-bytes of length 4)
+ private static final byte[] sCasPrivateInfo = hexStringToByteArray("00000000");
+
/**
* Convert a hex string into byte array.
*/
@@ -309,6 +312,9 @@
MediaFormat.MIMETYPE_AUDIO_SCRAMBLED.equals(mime)) {
MediaExtractor.CasInfo casInfo = extractor.getCasInfo(trackId);
if (casInfo != null) {
+ if (!Arrays.equals(sCasPrivateInfo, casInfo.getPrivateData())) {
+ throw new Error("Cas private data mismatch");
+ }
mMediaCas = new MediaCas(casInfo.getSystemId());
mMediaCas.provision(sProvisionStr);
extractor.setMediaCas(mMediaCas);
diff --git a/tests/tests/transition/src/android/transition/cts/ChangeBoundsTest.java b/tests/tests/transition/src/android/transition/cts/ChangeBoundsTest.java
index 71bb9f1..cabe7bf 100644
--- a/tests/tests/transition/src/android/transition/cts/ChangeBoundsTest.java
+++ b/tests/tests/transition/src/android/transition/cts/ChangeBoundsTest.java
@@ -71,7 +71,7 @@
private void resetChangeBoundsTransition() {
mListener = mock(Transition.TransitionListener.class);
mChangeBounds = new MyChangeBounds();
- mChangeBounds.setDuration(500);
+ mChangeBounds.setDuration(1000);
mChangeBounds.addListener(mListener);
mChangeBounds.setInterpolator(new LinearInterpolator());
mTransition = mChangeBounds;
diff --git a/tests/tests/view/res/layout/focus_finder_layout.xml b/tests/tests/view/res/layout/focus_finder_layout.xml
index 8f4dffb..1dea684 100644
--- a/tests/tests/view/res/layout/focus_finder_layout.xml
+++ b/tests/tests/view/res/layout/focus_finder_layout.xml
@@ -22,8 +22,7 @@
android:layout_alignParentTop="true">
<TableRow>
<android.view.cts.TestButton android:id="@+id/top_left_button"
- android:layout_width="20dp"
- android:layout_marginRight="40dp"
+ android:layout_width="60dp"
android:layout_height="match_parent"
android:text="TL" />
<android.view.cts.TestButton android:id="@+id/top_right_button"
diff --git a/tests/tests/view/src/android/view/cts/FocusFinderTest.java b/tests/tests/view/src/android/view/cts/FocusFinderTest.java
index 2505111..465b218 100644
--- a/tests/tests/view/src/android/view/cts/FocusFinderTest.java
+++ b/tests/tests/view/src/android/view/cts/FocusFinderTest.java
@@ -121,13 +121,14 @@
* | | |
* +---+---+
*/
- Rect rect = new Rect();
- mTopLeft.getDrawingRect(rect);
- rect.offset(mTopLeft.getWidth() / 2, 0);
- rect.inset(mTopLeft.getWidth() / 4, mTopLeft.getHeight() / 4);
+ int buttonHalfWidth = mTopLeft.getWidth() / 2;
+ Rect topRect = new Rect(mTopLeft.getLeft() + buttonHalfWidth,
+ mTopLeft.getTop(),
+ mTopLeft.getRight() + buttonHalfWidth,
+ mTopLeft.getBottom());
- verifytNextFocusFromRect(rect, View.FOCUS_LEFT, mTopLeft);
- verifytNextFocusFromRect(rect, View.FOCUS_RIGHT, mTopRight);
+ verifytNextFocusFromRect(topRect, View.FOCUS_LEFT, mTopLeft);
+ verifytNextFocusFromRect(topRect, View.FOCUS_RIGHT, mTopRight);
/*
* Create a small rectangle on the border between the top left and bottom left buttons.
@@ -138,12 +139,14 @@
* | | |
* +---+---+
*/
- mTopLeft.getDrawingRect(rect);
- rect.offset(0, mTopRight.getHeight() / 2);
- rect.inset(mTopLeft.getWidth() / 4, mTopLeft.getHeight() / 4);
+ int buttonHalfHeight = mTopLeft.getHeight() / 2;
+ Rect leftRect = new Rect(mTopLeft.getLeft(),
+ mTopLeft.getTop() + buttonHalfHeight,
+ mTopLeft.getRight(),
+ mTopLeft.getBottom() + buttonHalfHeight);
- verifytNextFocusFromRect(rect, View.FOCUS_UP, mTopLeft);
- verifytNextFocusFromRect(rect, View.FOCUS_DOWN, mBottomLeft);
+ verifytNextFocusFromRect(leftRect, View.FOCUS_UP, mTopLeft);
+ verifytNextFocusFromRect(leftRect, View.FOCUS_DOWN, mBottomLeft);
}
private void verifytNextFocusFromRect(Rect rect, int direction, View expectedNextFocus) {
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index 3168c60..7af6529 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -4855,6 +4855,30 @@
}
}
+ @Test
+ public void testSetTransitionVisibility() {
+ MockView view = new MockView(mContext);
+ view.setVisibility(View.GONE);
+ view.setParent(mMockParent);
+ mMockParent.reset();
+
+ // setTransitionVisibility shouldn't trigger requestLayout() on the parent
+ view.setTransitionVisibility(View.VISIBLE);
+
+ assertEquals(View.VISIBLE, view.getVisibility());
+ assertFalse(mMockParent.hasRequestLayout());
+
+ // Reset state
+ view.setVisibility(View.GONE);
+ mMockParent.reset();
+
+ // setVisibility should trigger requestLayout() on the parent
+ view.setVisibility(View.VISIBLE);
+
+ assertEquals(View.VISIBLE, view.getVisibility());
+ assertTrue(mMockParent.hasRequestLayout());
+ }
+
private static class MockDrawable extends Drawable {
private boolean mCalledSetTint = false;
diff --git a/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java b/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
index e76382e..0456667 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
@@ -29,6 +29,9 @@
import android.app.Activity;
import android.app.Instrumentation;
import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.MediumTest;
@@ -339,6 +342,42 @@
teardown();
}
+ @Test
+ public void testForceShowIcon_enabled() throws Throwable {
+ testForceShowIcon(true);
+ }
+
+ @Test
+ public void testForceShowIcon_disabled() throws Throwable {
+ testForceShowIcon(false);
+ }
+
+ private void testForceShowIcon(boolean forceShowIcon) throws Throwable {
+ mBuilder = new Builder().withForceShowIcon(forceShowIcon);
+ WidgetTestUtils.runOnMainAndLayoutSync(mActivityRule, mBuilder::configure, true);
+ final TestColorDrawable drawable = new TestColorDrawable(Color.BLUE);
+ mPopupMenu.getMenu().getItem(0).setIcon(drawable);
+ WidgetTestUtils.runOnMainAndDrawSync(
+ mActivityRule,
+ mActivity.findViewById(R.id.anchor_middle_left),
+ mBuilder::show
+ );
+ assertEquals(forceShowIcon, drawable.mWasDrawn);
+ }
+
+ private class TestColorDrawable extends ColorDrawable {
+ boolean mWasDrawn = false;
+ TestColorDrawable(final int color) {
+ super(color);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ super.draw(canvas);
+ mWasDrawn = true;
+ }
+ }
+
/**
* Inner helper class to configure an instance of {@link PopupMenu} for the specific test.
* The main reason for its existence is that once a popup menu is shown with the show() method,
@@ -367,6 +406,8 @@
private boolean mGroupDividerEnabled = false;
+ private boolean mForceShowIcon = false;
+
public Builder withMenuItemClickListener() {
mHasMenuItemClickListener = true;
return this;
@@ -409,7 +450,12 @@
return this;
}
- private void configure() {
+ public Builder withForceShowIcon(boolean forceShowIcon) {
+ mForceShowIcon = forceShowIcon;
+ return this;
+ }
+
+ public void configure() {
mAnchor = mActivity.findViewById(mAnchorId);
if (!mUseCustomGravity && !mUseCustomPopupResource) {
mPopupMenu = new PopupMenu(mActivity, mAnchor);
@@ -443,10 +489,14 @@
if (mGroupDividerEnabled) {
mPopupMenu.getMenu().setGroupDividerEnabled(true);
}
+
+ mPopupMenu.setForceShowIcon(mForceShowIcon);
}
public void show() {
- configure();
+ if (mPopupMenu == null) {
+ configure();
+ }
// Show the popup menu
mPopupMenu.show();
}