Merge \\\"Add test to detect some rendering inaccuracy.\\\" into nyc-dev am: f6df828780 am: 8350d5a913
am: 5b57a34915
Change-Id: Icadbfc82af5dd9a38c6f770286455ed255c7f939
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
index d7fa7a7..98a63c2 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
@@ -151,7 +151,7 @@
helpBuilder.append(" help: show this message.\n");
helpBuilder.append(" help all: show the complete tradefed help.\n");
helpBuilder.append(" version: show the version.\n");
- helpBuilder.append(" exit: gracefully exit the compatibiltiy console, waiting until all ");
+ helpBuilder.append(" exit: gracefully exit the compatibility console, waiting until all ");
helpBuilder.append("invocations have completed.\n");
helpBuilder.append("Run:\n");
final String runPrompt = " run <plan> ";
diff --git a/hostsidetests/compilation/src/android/cts/compilation/AdbRootDependentCompilationTest.java b/hostsidetests/compilation/src/android/cts/compilation/AdbRootDependentCompilationTest.java
index ab7dc43..24fad97 100644
--- a/hostsidetests/compilation/src/android/cts/compilation/AdbRootDependentCompilationTest.java
+++ b/hostsidetests/compilation/src/android/cts/compilation/AdbRootDependentCompilationTest.java
@@ -36,9 +36,17 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import static com.google.common.base.Preconditions.checkNotNull;
+
/**
- * Tests that profile guided compilation succeeds regardless of whether a runtime
- * profile of the target application is present on the device.
+ * Various integration tests for dex to oat compilation, with or without profiles.
+ * When changing this test, make sure it still passes in each of the following
+ * configurations:
+ * <ul>
+ * <li>On a 'user' build</li>
+ * <li>On a 'userdebug' build with system property 'dalvik.vm.usejitprofiles' set to false</li>
+ * <li>On a 'userdebug' build with system property 'dalvik.vm.usejitprofiles' set to true</li>
+ * </ul>
*/
public class AdbRootDependentCompilationTest extends DeviceTestCase {
private static final String TAG = AdbRootDependentCompilationTest.class.getSimpleName();
@@ -66,8 +74,6 @@
private ITestDevice mDevice;
private byte[] profileBytes;
private File localProfileFile;
- private String odexFilePath;
- private byte[] initialOdexFileContents;
private File apkFile;
private boolean mIsRoot;
private boolean mNewlyObtainedRoot;
@@ -101,20 +107,6 @@
localProfileFile = File.createTempFile("compilationtest", "prof");
Files.write(profileBytes, localProfileFile);
assertTrue("empty profile", profileBytes.length > 0); // sanity check
-
- if (mIsRoot) {
- // ensure no profiles initially present
- for (ProfileLocation profileLocation : ProfileLocation.values()) {
- String clientPath = profileLocation.getPath();
- if (mDevice.doesFileExist(clientPath)) {
- executeAdbCommand(0, "shell", "rm", clientPath);
- }
- }
- executeCompile(/* force */ true);
- this.odexFilePath = getOdexFilePath();
- this.initialOdexFileContents = readFileOnClient(odexFilePath);
- assertTrue("empty odex file", initialOdexFileContents.length > 0); // sanity check
- }
}
@Override
@@ -128,6 +120,29 @@
super.tearDown();
}
+ /**
+ * Tests compilation using {@code -r bg-dexopt -f}.
+ */
+ public void testCompile_bgDexopt() throws Exception {
+ if (!canRunTest(EnumSet.noneOf(ProfileLocation.class))) {
+ return;
+ }
+ // Usually "interpret-only"
+ String expectedInstallFilter = checkNotNull(mDevice.getProperty("pm.dexopt.install"));
+ // Usually "speed-profile"
+ String expectedBgDexoptFilter = checkNotNull(mDevice.getProperty("pm.dexopt.bg-dexopt"));
+
+ String odexPath = getOdexFilePath();
+ assertEquals(expectedInstallFilter, getCompilerFilter(odexPath));
+
+ // Without -f, the compiler would only run if it judged the bg-dexopt filter to
+ // be "better" than the install filter. However manufacturers can change those
+ // values so we don't want to depend here on the resulting filter being better.
+ executeCompile("-r", "bg-dexopt", "-f");
+
+ assertEquals(expectedBgDexoptFilter, getCompilerFilter(odexPath));
+ }
+
/*
The tests below test the remaining combinations of the "ref" (reference) and
"cur" (current) profile being available. The "cur" profile gets moved/merged
@@ -140,53 +155,31 @@
profile_assistant, it may only be available in "ref".
*/
- public void testForceCompile_noProfile() throws Exception {
- Set<ProfileLocation> profileLocations = EnumSet.noneOf(ProfileLocation.class);
- if (!canRunTest(profileLocations)) {
- return;
- }
- compileWithProfilesAndCheckFilter(profileLocations);
- byte[] odexFileContents = readFileOnClient(odexFilePath);
- assertBytesEqual(initialOdexFileContents, odexFileContents);
+ public void testCompile_noProfile() throws Exception {
+ compileWithProfilesAndCheckFilter(false /* expectOdexChange */,
+ EnumSet.noneOf(ProfileLocation.class));
}
- public void testForceCompile_curProfile() throws Exception {
- Set<ProfileLocation> profileLocations = EnumSet.of(ProfileLocation.CUR);
- if (!canRunTest(profileLocations)) {
- return;
+ public void testCompile_curProfile() throws Exception {
+ boolean didRun = compileWithProfilesAndCheckFilter(true /* expectOdexChange */,
+ EnumSet.of(ProfileLocation.CUR));
+ if (didRun) {
+ assertTrue("ref profile should have been created by the compiler",
+ mDevice.doesFileExist(ProfileLocation.REF.getPath()));
}
- compileWithProfilesAndCheckFilter(profileLocations);
- assertTrue("ref profile should have been created by the compiler",
- mDevice.doesFileExist(ProfileLocation.REF.getPath()));
- assertFalse("odex compiled with cur profile should differ from the initial one without",
- Arrays.equals(initialOdexFileContents, readFileOnClient(odexFilePath)));
}
- public void testForceCompile_refProfile() throws Exception {
- Set<ProfileLocation> profileLocations = EnumSet.of(ProfileLocation.REF);
- if (!canRunTest(profileLocations)) {
- return;
- }
- compileWithProfilesAndCheckFilter(profileLocations);
+ public void testCompile_refProfile() throws Exception {
+ compileWithProfilesAndCheckFilter(false /* expectOdexChange */,
+ EnumSet.of(ProfileLocation.REF));
// We assume that the compiler isn't smart enough to realize that the
// previous odex was compiled before the ref profile was in place, even
// though theoretically it could be.
- byte[] odexFileContents = readFileOnClient(odexFilePath);
- assertBytesEqual(initialOdexFileContents, odexFileContents);
}
- public void testForceCompile_curAndRefProfile() throws Exception {
- Set<ProfileLocation> profileLocations = EnumSet.of(
- ProfileLocation.CUR, ProfileLocation.REF);
- if (!canRunTest(profileLocations)) {
- return;
- }
- compileWithProfilesAndCheckFilter(profileLocations);
- // We assume that the compiler isn't smart enough to realize that the
- // previous odex was compiled before the ref profile was in place, even
- // though theoretically it could be.
- byte[] odexFileContents = readFileOnClient(odexFilePath);
- assertBytesEqual(initialOdexFileContents, odexFileContents);
+ public void testCompile_curAndRefProfile() throws Exception {
+ compileWithProfilesAndCheckFilter(false /* expectOdexChange */,
+ EnumSet.of(ProfileLocation.CUR, ProfileLocation.REF));
}
private byte[] readFileOnClient(String clientPath) throws Exception {
@@ -204,29 +197,58 @@
/**
* Places {@link #profileBytes} in the specified locations, recompiles (without -f)
* and checks the compiler-filter in the odex file.
+ *
+ * @return whether the test ran (as opposed to early exit)
*/
- private void compileWithProfilesAndCheckFilter(Set<ProfileLocation> profileLocations)
+ private boolean compileWithProfilesAndCheckFilter(boolean expectOdexChange,
+ Set<ProfileLocation> profileLocations)
throws Exception {
+ if (!canRunTest(profileLocations)) {
+ return false;
+ }
+ // ensure no profiles initially present
+ for (ProfileLocation profileLocation : ProfileLocation.values()) {
+ String clientPath = profileLocation.getPath();
+ if (mDevice.doesFileExist(clientPath)) {
+ executeAdbCommand(0, "shell", "rm", clientPath);
+ }
+ }
+ executeCompile("-m", "speed-profile", "-f");
+ String odexFilePath = getOdexFilePath();
+ byte[] initialOdexFileContents = readFileOnClient(odexFilePath);
+ assertTrue("empty odex file", initialOdexFileContents.length > 0); // sanity check
+
for (ProfileLocation profileLocation : profileLocations) {
writeProfile(profileLocation);
}
- executeCompile(/* force */ false);
+ executeCompile("-m", "speed-profile");
// Confirm the compiler-filter used in creating the odex file
String compilerFilter = getCompilerFilter(odexFilePath);
assertEquals("compiler-filter", "speed-profile", compilerFilter);
+
+ byte[] odexFileContents = readFileOnClient(odexFilePath);
+ boolean odexChanged = !(Arrays.equals(initialOdexFileContents, odexFileContents));
+ if (odexChanged && !expectOdexChange) {
+ String msg = String.format(Locale.US, "Odex file without filters (%d bytes) "
+ + "unexpectedly different from odex file (%d bytes) compiled with filters: %s",
+ initialOdexFileContents.length, odexFileContents.length, profileLocations);
+ fail(msg);
+ } else if (!odexChanged && expectOdexChange) {
+ fail("odex file should have changed when recompiling with " + profileLocations);
+ }
+ return true;
}
/**
* Invokes the dex2oat compiler on the client.
+ *
+ * @param compileOptions extra options to pass to the compiler on the command line
*/
- private void executeCompile(boolean force) throws Exception {
- List<String> command = new ArrayList<>(Arrays.asList("shell", "cmd", "package", "compile",
- "-m", "speed-profile"));
- if (force) {
- command.add("-f");
- }
+ private void executeCompile(String... compileOptions) throws Exception {
+ List<String> command = new ArrayList<>(Arrays.asList("shell", "cmd", "package", "compile"));
+ command.addAll(Arrays.asList(compileOptions));
command.add(APPLICATION_PACKAGE);
String[] commandArray = command.toArray(new String[0]);
assertEquals("Success", executeAdbCommand(1, commandArray)[0]);
@@ -292,8 +314,8 @@
}
/**
- * Returns whether a test can run in the current device configuration
- * and for the given profileLocations. This allows tests to exit early.
+ * Returns whether a test that uses the given profileLocations can run
+ * in the current device configuration. This allows tests to exit early.
*
* <p>Ideally we'd like tests to be marked as skipped/ignored or similar
* rather than passing if they can't run on the current device, but that
@@ -332,10 +354,4 @@
String[] lines = output.equals("") ? new String[0] : output.split("\n");
return lines;
}
-
- private static void assertBytesEqual(byte[] expected, byte[] actual) {
- String msg = String.format("Expected %d bytes differ from actual %d bytes",
- expected.length, actual.length);
- assertTrue(msg, Arrays.equals(expected, actual));
- }
}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api23/Android.mk b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api23/Android.mk
index b1c35aac..5d32955 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api23/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api23/Android.mk
@@ -26,7 +26,7 @@
LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctsdeviceutil ctstestrunner ub-uiautomator
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := test_current
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/../res
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/Android.mk b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/Android.mk
index 7d08bc3..884bb0b 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/Android.mk
@@ -26,7 +26,7 @@
LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctsdeviceutil ctstestrunner ub-uiautomator
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := test_current
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/../res
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
index 744db8f..1c9d24d 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
@@ -25,7 +25,8 @@
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
- <application
+ <!-- Add a network security config that trusts user added CAs for tests -->
+ <application android:networkSecurityConfig="@xml/network_security_config"
android:testOnly="true">
<uses-library android:name="android.test.runner" />
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/res/xml/network_security_config.xml b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/xml/network_security_config.xml
similarity index 100%
rename from hostsidetests/devicepolicy/app/DeviceOwner/res/xml/network_security_config.xml
rename to hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/xml/network_security_config.xml
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java
index 34566a1..01a5a3a 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java
@@ -17,6 +17,7 @@
package com.android.cts.deviceandprofileowner;
import android.os.Bundle;
+import android.os.UserManager;
import com.android.cts.deviceandprofileowner.vpn.VpnTestHelper;
@@ -63,6 +64,18 @@
VpnTestHelper.checkPing(TEST_ADDRESS);
}
+ public void testDisallowConfigVpn() throws Exception {
+ mDevicePolicyManager.addUserRestriction(
+ ADMIN_RECEIVER_COMPONENT, UserManager.DISALLOW_CONFIG_VPN);
+ try {
+ testAlwaysOnVpn();
+ } finally {
+ // clear the user restriction
+ mDevicePolicyManager.clearUserRestriction(ADMIN_RECEIVER_COMPONENT,
+ UserManager.DISALLOW_CONFIG_VPN);
+ }
+ }
+
public void testAllowedApps() throws Exception {
final Bundle restrictions = new Bundle();
restrictions.putStringArray(RESTRICTION_ALLOWED, new String[] {mPackageName});
@@ -97,4 +110,3 @@
assertNull(mDevicePolicyManager.getAlwaysOnVpnPackage(ADMIN_RECEIVER_COMPONENT));
}
}
-
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CaCertManagementTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/CaCertManagementTest.java
similarity index 84%
rename from hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CaCertManagementTest.java
rename to hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/CaCertManagementTest.java
index 3e692c3..feb4a9b 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CaCertManagementTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/CaCertManagementTest.java
@@ -13,8 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.cts.deviceowner;
+package com.android.cts.deviceandprofileowner;
+import android.content.ComponentName;
import android.net.http.X509TrustManagerExtensions;
import android.security.NetworkSecurityPolicy;
@@ -32,17 +33,19 @@
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
-import static com.android.cts.deviceowner.FakeKeys.FAKE_DSA_1;
-import static com.android.cts.deviceowner.FakeKeys.FAKE_RSA_1;
+import static android.cts.util.FakeKeys.FAKE_DSA_1;
+import static android.cts.util.FakeKeys.FAKE_RSA_1;
-public class CaCertManagementTest extends BaseDeviceOwnerTest {
+public class CaCertManagementTest extends BaseDeviceAdminTest {
+ private final ComponentName mAdmin = ADMIN_RECEIVER_COMPONENT;
+
/**
* Test: device admins should be able to list all installed certs.
*
* <p>The list of certificates must never be {@code null}.
*/
public void testCanRetrieveListOfInstalledCaCerts() {
- List<byte[]> caCerts = mDevicePolicyManager.getInstalledCaCerts(getWho());
+ List<byte[]> caCerts = mDevicePolicyManager.getInstalledCaCerts(mAdmin);
assertNotNull(caCerts);
}
@@ -54,11 +57,11 @@
assertUninstalled(FAKE_RSA_1.caCertificate);
assertUninstalled(FAKE_DSA_1.caCertificate);
- assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_RSA_1.caCertificate));
+ assertTrue(mDevicePolicyManager.installCaCert(mAdmin, FAKE_RSA_1.caCertificate));
assertInstalled(FAKE_RSA_1.caCertificate);
assertUninstalled(FAKE_DSA_1.caCertificate);
- mDevicePolicyManager.uninstallCaCert(getWho(), FAKE_RSA_1.caCertificate);
+ mDevicePolicyManager.uninstallCaCert(mAdmin, FAKE_RSA_1.caCertificate);
assertUninstalled(FAKE_RSA_1.caCertificate);
assertUninstalled(FAKE_DSA_1.caCertificate);
}
@@ -68,14 +71,14 @@
*/
public void testUninstallationIsSelective()
throws CertificateException, GeneralSecurityException {
- assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_RSA_1.caCertificate));
- assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_DSA_1.caCertificate));
+ assertTrue(mDevicePolicyManager.installCaCert(mAdmin, FAKE_RSA_1.caCertificate));
+ assertTrue(mDevicePolicyManager.installCaCert(mAdmin, FAKE_DSA_1.caCertificate));
- mDevicePolicyManager.uninstallCaCert(getWho(), FAKE_DSA_1.caCertificate);
+ mDevicePolicyManager.uninstallCaCert(mAdmin, FAKE_DSA_1.caCertificate);
assertInstalled(FAKE_RSA_1.caCertificate);
assertUninstalled(FAKE_DSA_1.caCertificate);
- mDevicePolicyManager.uninstallCaCert(getWho(), FAKE_RSA_1.caCertificate);
+ mDevicePolicyManager.uninstallCaCert(mAdmin, FAKE_RSA_1.caCertificate);
}
/**
@@ -84,10 +87,10 @@
*/
public void testCanUninstallAllUserCaCerts()
throws CertificateException, GeneralSecurityException {
- assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_RSA_1.caCertificate));
- assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_DSA_1.caCertificate));
+ assertTrue(mDevicePolicyManager.installCaCert(mAdmin, FAKE_RSA_1.caCertificate));
+ assertTrue(mDevicePolicyManager.installCaCert(mAdmin, FAKE_DSA_1.caCertificate));
- mDevicePolicyManager.uninstallAllUserCaCerts(getWho());
+ mDevicePolicyManager.uninstallAllUserCaCerts(mAdmin);
assertUninstalled(FAKE_RSA_1.caCertificate);
assertUninstalled(FAKE_DSA_1.caCertificate);
}
@@ -131,10 +134,10 @@
*/
private boolean isCaCertInstalledAndTrusted(Certificate caCert)
throws GeneralSecurityException, CertificateException {
- boolean installed = mDevicePolicyManager.hasCaCertInstalled(getWho(), caCert.getEncoded());
+ boolean installed = mDevicePolicyManager.hasCaCertInstalled(mAdmin, caCert.getEncoded());
boolean listed = false;
- for (byte[] certBuffer : mDevicePolicyManager.getInstalledCaCerts(getWho())) {
+ for (byte[] certBuffer : mDevicePolicyManager.getInstalledCaCerts(mAdmin)) {
if (caCert.equals(readCertificate(certBuffer))) {
listed = true;
}
@@ -153,7 +156,7 @@
boolean userAddedCertificate = xtm.isUserAddedCertificate((X509Certificate) caCert);
// All three responses should match - if an installed certificate isn't trusted or (worse)
- // a trusted certificate isn't even installed we should
+ // a trusted certificate isn't even installed we should fail now, loudly.
assertEquals(installed, listed);
assertEquals(installed, trusted);
assertEquals(installed, userAddedCertificate);
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/vpn/VpnTestHelper.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/vpn/VpnTestHelper.java
index 3072251..41bb626 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/vpn/VpnTestHelper.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/vpn/VpnTestHelper.java
@@ -65,7 +65,6 @@
private static final int ICMP_ECHO_REQUEST = 0x08;
private static final int ICMP_ECHO_REPLY = 0x00;
private static final int NETWORK_TIMEOUT_MS = 5000;
- private static final int NETWORK_SETTLE_GRACE_MS = 100;
private static final ComponentName ADMIN_RECEIVER_COMPONENT =
BaseDeviceAdminTest.ADMIN_RECEIVER_COMPONENT;
@@ -93,8 +92,6 @@
if (!vpnLatch.await(NETWORK_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
fail("Took too long waiting to establish a VPN-backed connection");
}
- // Give the VPN a moment to start transmitting data.
- Thread.sleep(NETWORK_SETTLE_GRACE_MS);
} catch (InterruptedException | PackageManager.NameNotFoundException e) {
fail("Failed to send ping: " + e);
} finally {
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk b/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
index 18d1b8b..197f5a7 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
@@ -26,7 +26,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner compatibility-device-util
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctsdeviceutil compatibility-device-util
LOCAL_SDK_VERSION := test_current
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
index 64d4079..07d006c 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
@@ -25,8 +25,7 @@
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
- <!-- Add a network security config that trusts user added CAs for tests -->
- <application android:networkSecurityConfig="@xml/network_security_config"
+ <application
android:testOnly="true">
<uses-library android:name="android.test.runner" />
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java
index 219dfc2..cc4a8b0 100755
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java
@@ -15,8 +15,8 @@
*/
package com.android.cts.deviceowner;
+import static android.cts.util.FakeKeys.FAKE_RSA_1;
import static com.android.cts.deviceowner.BaseDeviceOwnerTest.getWho;
-import static com.android.cts.deviceowner.FakeKeys.FAKE_RSA_1;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
diff --git a/hostsidetests/devicepolicy/app/LauncherTests/Android.mk b/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
index eb4a091..19fd3bd 100644
--- a/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
+++ b/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
@@ -26,7 +26,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
-LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctstestrunner android-support-test
LOCAL_SDK_VERSION := current
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk b/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
index 85c74f9..7003012 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
@@ -27,7 +27,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctstestrunner compatibility-device-util \
- ub-uiautomator
+ ub-uiautomator android-support-test
LOCAL_SDK_VERSION := current
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index 7b40ff1..c2a9bc1 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -110,6 +110,13 @@
super.tearDown();
}
+ public void testCaCertManagement() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ executeDeviceTestClass(".CaCertManagementTest");
+ }
+
public void testResetPassword() throws Exception {
if (!mHasFeature) {
return;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 4748b35..a877525 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -84,10 +84,6 @@
super.tearDown();
}
- public void testCaCertManagement() throws Exception {
- executeDeviceOwnerTest("CaCertManagementTest");
- }
-
public void testDeviceOwnerSetup() throws Exception {
executeDeviceOwnerTest("DeviceOwnerSetupTest");
}
diff --git a/hostsidetests/net/aidl/Android.mk b/hostsidetests/net/aidl/Android.mk
index a7ec6ef..4aa55b6 100644
--- a/hostsidetests/net/aidl/Android.mk
+++ b/hostsidetests/net/aidl/Android.mk
@@ -19,4 +19,4 @@
LOCAL_SDK_VERSION := current
LOCAL_SRC_FILES := com/android/cts/net/hostside/IRemoteSocketFactory.aidl
LOCAL_MODULE := CtsHostsideNetworkTestsAidl
-include $(BUILD_JAVA_LIBRARY)
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/hostsidetests/numberblocking/app/Android.mk b/hostsidetests/numberblocking/app/Android.mk
index 492a2ec..5755f84 100644
--- a/hostsidetests/numberblocking/app/Android.mk
+++ b/hostsidetests/numberblocking/app/Android.mk
@@ -27,7 +27,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
# tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/FakeKeys.java b/libs/deviceutil/src/android/cts/util/FakeKeys.java
similarity index 99%
rename from hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/FakeKeys.java
rename to libs/deviceutil/src/android/cts/util/FakeKeys.java
index 11df8e5..f3814a4 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/FakeKeys.java
+++ b/libs/deviceutil/src/android/cts/util/FakeKeys.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.cts.deviceowner;
+package android.cts.util;
// Copied from cts/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
diff --git a/libs/deviceutil/src/android/cts/util/PollingCheck.java b/libs/deviceutil/src/android/cts/util/PollingCheck.java
index 3a08c7e..0e255a1 100644
--- a/libs/deviceutil/src/android/cts/util/PollingCheck.java
+++ b/libs/deviceutil/src/android/cts/util/PollingCheck.java
@@ -82,4 +82,13 @@
}
}.run();
}
+
+ public static void waitFor(long timeout, final PollingCheckCondition condition) {
+ new PollingCheck(timeout) {
+ @Override
+ protected boolean check() {
+ return condition.canProceed();
+ }
+ }.run();
+ }
}
diff --git a/libs/deviceutil/src/android/cts/util/WidgetTestUtils.java b/libs/deviceutil/src/android/cts/util/WidgetTestUtils.java
index 813672e..740513e 100644
--- a/libs/deviceutil/src/android/cts/util/WidgetTestUtils.java
+++ b/libs/deviceutil/src/android/cts/util/WidgetTestUtils.java
@@ -33,10 +33,11 @@
*/
public class WidgetTestUtils {
/**
- * Assert that two bitmaps are equal.
+ * Assert that two bitmaps have identical content (same dimensions, same configuration,
+ * same pixel content).
*
- * @param Bitmap b1 the first bitmap which needs to compare.
- * @param Bitmap b2 the second bitmap which needs to compare.
+ * @param b1 the first bitmap which needs to compare.
+ * @param b2 the second bitmap which needs to compare.
*/
public static void assertEquals(Bitmap b1, Bitmap b2) {
if (b1 == b2) {
diff --git a/tests/app/Android.mk b/tests/app/Android.mk
index 775e679..6ce0148 100644
--- a/tests/app/Android.mk
+++ b/tests/app/Android.mk
@@ -23,7 +23,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common voip-common org.apache.http.legacy
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner ctstestserver mockito-target
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner ctstestserver mockito-target android-support-test
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/app/app/AndroidManifest.xml b/tests/app/app/AndroidManifest.xml
index 10a6792..2ac5dbb 100644
--- a/tests/app/app/AndroidManifest.xml
+++ b/tests/app/app/AndroidManifest.xml
@@ -196,7 +196,7 @@
</intent-filter>
</activity>
- <activity android:name="android.app.stubs.ChildTabActivity" android:label="ChildTabActivity" />
+ <activity android:name="android.app.stubs.FragmentResultActivity" android:label="FragmentResultActivity" />
<activity android:name="android.app.stubs.LauncherActivityStub"
android:label="LauncherActivityStub" >
diff --git a/tests/app/app/src/android/app/stubs/FragmentResultActivity.java b/tests/app/app/src/android/app/stubs/FragmentResultActivity.java
new file mode 100644
index 0000000..364d093
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/FragmentResultActivity.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+package android.app.stubs;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * A simple Activity used to return a result.
+ */
+public class FragmentResultActivity extends Activity {
+ public static final String EXTRA_RESULT_CODE = "result";
+ public static final String EXTRA_RESULT_CONTENT = "result_content";
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ int resultCode = getIntent().getIntExtra(EXTRA_RESULT_CODE, Activity.RESULT_OK);
+ String result = getIntent().getStringExtra(EXTRA_RESULT_CONTENT);
+ Intent intent = new Intent();
+ intent.putExtra(EXTRA_RESULT_CONTENT, result);
+ setResult(resultCode, intent);
+ finish();
+ }
+}
diff --git a/tests/app/app/src/android/app/stubs/FragmentTestActivity.java b/tests/app/app/src/android/app/stubs/FragmentTestActivity.java
index a421895..a5f54bc 100644
--- a/tests/app/app/src/android/app/stubs/FragmentTestActivity.java
+++ b/tests/app/app/src/android/app/stubs/FragmentTestActivity.java
@@ -19,6 +19,7 @@
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
+import android.content.Intent;
import android.os.Bundle;
import android.transition.Transition;
import android.transition.Transition.TransitionListener;
diff --git a/tests/app/app/src/android/app/stubs/MockTabActivity.java b/tests/app/app/src/android/app/stubs/MockTabActivity.java
index 247cfe0..722ac69 100644
--- a/tests/app/app/src/android/app/stubs/MockTabActivity.java
+++ b/tests/app/app/src/android/app/stubs/MockTabActivity.java
@@ -40,7 +40,7 @@
final TabHost tabHost = getTabHost();
tabHost.addTab(tabHost.newTabSpec(TAB1).setIndicator(TAB1)
- .setContent(new Intent(this, ChildTabActivity.class)));
+ .setContent(new Intent(this, MockActivity.class)));
tabHost.addTab(tabHost.newTabSpec(TAB2).setIndicator(TAB2)
.setContent(new Intent(this, MockActivity.class)));
diff --git a/tests/app/src/android/app/cts/ActivityActionModeTest.java b/tests/app/src/android/app/cts/ActivityActionModeTest.java
new file mode 100644
index 0000000..b74e737
--- /dev/null
+++ b/tests/app/src/android/app/cts/ActivityActionModeTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+package android.app.cts;
+
+import static org.mockito.Mockito.*;
+
+import android.app.stubs.MockActivity;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.ActionMode;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ActivityActionModeTest {
+
+ private ActionMode.Callback mCallback;
+
+ @Rule
+ public ActivityTestRule<MockActivity> mActivityRule =
+ new ActivityTestRule<>(MockActivity.class);
+
+ @Before
+ public void setUp() {
+ mCallback = mock(ActionMode.Callback.class);
+ when(mCallback.onCreateActionMode(any(), any())).thenReturn(true);
+ when(mCallback.onPrepareActionMode(any(), any())).thenReturn(true);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testStartPrimaryActionMode() {
+ final ActionMode mode = mActivityRule.getActivity().startActionMode(
+ mCallback, ActionMode.TYPE_PRIMARY);
+
+ assertNotNull(mode);
+ assertEquals(ActionMode.TYPE_PRIMARY, mode.getType());
+ }
+
+ @Test
+ @UiThreadTest
+ public void testStartFloatingActionMode() {
+ final ActionMode mode = mActivityRule.getActivity().startActionMode(
+ mCallback, ActionMode.TYPE_FLOATING);
+
+ assertNotNull(mode);
+ assertEquals(ActionMode.TYPE_FLOATING, mode.getType());
+ }
+
+ @Test
+ @UiThreadTest
+ public void testStartTypelessActionMode() {
+ final ActionMode mode = mActivityRule.getActivity().startActionMode(mCallback);
+
+ assertNotNull(mode);
+ assertEquals(ActionMode.TYPE_PRIMARY, mode.getType());
+ }
+}
diff --git a/tests/app/src/android/app/cts/FragmentReceiveResultTest.java b/tests/app/src/android/app/cts/FragmentReceiveResultTest.java
new file mode 100644
index 0000000..b22ab6c
--- /dev/null
+++ b/tests/app/src/android/app/cts/FragmentReceiveResultTest.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+package android.app.cts;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+import static junit.framework.TestCase.fail;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.Instrumentation;
+import android.app.PendingIntent;
+import android.app.stubs.FragmentResultActivity;
+import android.app.stubs.FragmentTestActivity;
+import android.app.stubs.R;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests Fragment's startActivityForResult and startIntentSenderForResult.
+ */
+public class FragmentReceiveResultTest extends
+ ActivityInstrumentationTestCase2<FragmentTestActivity> {
+
+ private FragmentTestActivity mActivity;
+ private TestFragment mFragment;
+
+ public FragmentReceiveResultTest() {
+ super(FragmentTestActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mActivity = getActivity();
+ mFragment = attachTestFragment();
+ }
+
+ @SmallTest
+ public void testStartActivityForResultOk() {
+ startActivityForResult(10, Activity.RESULT_OK, "content 10");
+
+ assertTrue("Fragment should receive result", mFragment.mHasResult);
+ assertEquals(10, mFragment.mRequestCode);
+ assertEquals(Activity.RESULT_OK, mFragment.mResultCode);
+ assertEquals("content 10", mFragment.mResultContent);
+ }
+
+ @SmallTest
+ public void testStartActivityForResultCanceled() {
+ startActivityForResult(20, Activity.RESULT_CANCELED, "content 20");
+
+ assertTrue("Fragment should receive result", mFragment.mHasResult);
+ assertEquals(20, mFragment.mRequestCode);
+ assertEquals(Activity.RESULT_CANCELED, mFragment.mResultCode);
+ assertEquals("content 20", mFragment.mResultContent);
+ }
+
+ @SmallTest
+ public void testStartIntentSenderForResultOk() {
+ startIntentSenderForResult(30, Activity.RESULT_OK, "content 30");
+
+ assertTrue("Fragment should receive result", mFragment.mHasResult);
+ assertEquals(30, mFragment.mRequestCode);
+ assertEquals(Activity.RESULT_OK, mFragment.mResultCode);
+ assertEquals("content 30", mFragment.mResultContent);
+ }
+
+ @SmallTest
+ public void testStartIntentSenderForResultCanceled() {
+ startIntentSenderForResult(40, Activity.RESULT_CANCELED, "content 40");
+
+ assertTrue("Fragment should receive result", mFragment.mHasResult);
+ assertEquals(40, mFragment.mRequestCode);
+ assertEquals(Activity.RESULT_CANCELED, mFragment.mResultCode);
+ assertEquals("content 40", mFragment.mResultContent);
+ }
+
+ private TestFragment attachTestFragment() {
+ final TestFragment fragment = new TestFragment();
+ getInstrumentation().waitForIdleSync();
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ mActivity.getFragmentManager().beginTransaction()
+ .add(R.id.content, fragment)
+ .addToBackStack(null)
+ .commitAllowingStateLoss();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+ return fragment;
+ }
+
+ private void startActivityForResult(final int requestCode, final int resultCode,
+ final String content) {
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ Intent intent = new Intent(mActivity, FragmentResultActivity.class);
+ intent.putExtra(FragmentResultActivity.EXTRA_RESULT_CODE, resultCode);
+ intent.putExtra(FragmentResultActivity.EXTRA_RESULT_CONTENT, content);
+
+ mFragment.startActivityForResult(intent, requestCode);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+ }
+
+ private void startIntentSenderForResult(final int requestCode, final int resultCode,
+ final String content) {
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ Intent intent = new Intent(mActivity, FragmentResultActivity.class);
+ intent.putExtra(FragmentResultActivity.EXTRA_RESULT_CODE, resultCode);
+ intent.putExtra(FragmentResultActivity.EXTRA_RESULT_CONTENT, content);
+
+ PendingIntent pendingIntent = PendingIntent.getActivity(mActivity,
+ requestCode, intent, 0);
+
+ try {
+ mFragment.startIntentSenderForResult(pendingIntent.getIntentSender(),
+ requestCode, null, 0, 0, 0, null);
+ } catch (IntentSender.SendIntentException e) {
+ fail("IntentSender failed");
+ }
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+ }
+
+ public static class TestFragment extends Fragment {
+ boolean mHasResult = false;
+ int mRequestCode = -1;
+ int mResultCode = 100;
+ String mResultContent;
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ mHasResult = true;
+ mRequestCode = requestCode;
+ mResultCode = resultCode;
+ mResultContent = data.getStringExtra(FragmentResultActivity.EXTRA_RESULT_CONTENT);
+ }
+ }
+
+}
diff --git a/tests/app/src/android/app/cts/FragmentTransactionTest.java b/tests/app/src/android/app/cts/FragmentTransactionTest.java
new file mode 100644
index 0000000..2ff69a7
--- /dev/null
+++ b/tests/app/src/android/app/cts/FragmentTransactionTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+package android.app.cts;
+
+import android.app.Fragment;
+import android.app.stubs.FragmentTestActivity;
+import android.app.stubs.R;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static junit.framework.TestCase.*;
+
+/**
+ * Tests usage of the {@link android.app.FragmentTransaction} class.
+ */
+@RunWith(AndroidJUnit4.class)
+public class FragmentTransactionTest {
+
+ @Rule
+ public ActivityTestRule<FragmentTestActivity> mActivityRule =
+ new ActivityTestRule<>(FragmentTestActivity.class);
+
+ private FragmentTestActivity mActivity;
+
+ @Before
+ public void setUp() {
+ mActivity = mActivityRule.getActivity();
+ }
+
+ @Test
+ public void testAddTransactionWithValidFragment() {
+ final Fragment fragment = new CorrectFragment();
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ mActivity.getFragmentManager().beginTransaction()
+ .add(R.id.content, fragment)
+ .addToBackStack(null)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ }
+ });
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ assertTrue(fragment.isAdded());
+ }
+
+ @Test
+ public void testAddTransactionWithPrivateFragment() {
+ final Fragment fragment = new PrivateFragment();
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ boolean exceptionThrown = false;
+ try {
+ mActivity.getFragmentManager().beginTransaction()
+ .add(R.id.content, fragment)
+ .addToBackStack(null)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ } catch (IllegalStateException e) {
+ exceptionThrown = true;
+ } finally {
+ assertTrue("Exception should be thrown", exceptionThrown);
+ assertFalse("Fragment shouldn't be added", fragment.isAdded());
+ }
+ }
+ });
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ }
+
+ @Test
+ public void testAddTransactionWithPackagePrivateFragment() {
+ final Fragment fragment = new PackagePrivateFragment();
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ boolean exceptionThrown = false;
+ try {
+ mActivity.getFragmentManager().beginTransaction()
+ .add(R.id.content, fragment)
+ .addToBackStack(null)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ } catch (IllegalStateException e) {
+ exceptionThrown = true;
+ } finally {
+ assertTrue("Exception should be thrown", exceptionThrown);
+ assertFalse("Fragment shouldn't be added", fragment.isAdded());
+ }
+ }
+ });
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ }
+
+ @Test
+ public void testAddTransactionWithAnonymousFragment() {
+ final Fragment fragment = new Fragment() {};
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ boolean exceptionThrown = false;
+ try {
+ mActivity.getFragmentManager().beginTransaction()
+ .add(R.id.content, fragment)
+ .addToBackStack(null)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ } catch (IllegalStateException e) {
+ exceptionThrown = true;
+ } finally {
+ assertTrue("Exception should be thrown", exceptionThrown);
+ assertFalse("Fragment shouldn't be added", fragment.isAdded());
+ }
+ }
+ });
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ }
+
+ @Test
+ public void testAddTransactionWithNonStaticFragment() {
+ final Fragment fragment = new NonStaticFragment();
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ boolean exceptionThrown = false;
+ try {
+ mActivity.getFragmentManager().beginTransaction()
+ .add(R.id.content, fragment)
+ .addToBackStack(null)
+ .commit();
+ mActivity.getFragmentManager().executePendingTransactions();
+ } catch (IllegalStateException e) {
+ exceptionThrown = true;
+ } finally {
+ assertTrue("Exception should be thrown", exceptionThrown);
+ assertFalse("Fragment shouldn't be added", fragment.isAdded());
+ }
+ }
+ });
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ }
+
+ public static class CorrectFragment extends Fragment {}
+
+ private static class PrivateFragment extends Fragment {}
+
+ private static class PackagePrivateFragment extends Fragment {}
+
+ private class NonStaticFragment extends Fragment {}
+}
diff --git a/tests/aslr/src/AslrMallocTest.cpp b/tests/aslr/src/AslrMallocTest.cpp
index 6e773cb..91a36e2 100644
--- a/tests/aslr/src/AslrMallocTest.cpp
+++ b/tests/aslr/src/AslrMallocTest.cpp
@@ -157,7 +157,9 @@
return EXIT_FAILURE;
}
- printf("%p", malloc(size));
+ void* p = malloc(size);
+ printf("%p", p);
+ free(p);
return EXIT_SUCCESS;
}
#endif
diff --git a/tests/camera/libctscamera2jni/native-camera-jni.cpp b/tests/camera/libctscamera2jni/native-camera-jni.cpp
index db687bf..4a3620e 100644
--- a/tests/camera/libctscamera2jni/native-camera-jni.cpp
+++ b/tests/camera/libctscamera2jni/native-camera-jni.cpp
@@ -345,7 +345,7 @@
class StaticInfo {
public:
- StaticInfo(ACameraMetadata* chars) : mChars(chars) {}
+ explicit StaticInfo(ACameraMetadata* chars) : mChars(chars) {}
bool isColorOutputSupported() {
return isCapabilitySupported(ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 5ea4322..86839eb 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -244,19 +244,6 @@
bug: 23779168
},
{
- description: "New assist tests that do not yet have a track record.",
- names: [
- "android.assist.cts.AssistantContentViewTest",
- "android.assist.cts.ExtraAssistDataTest",
- "android.assist.cts.FocusChangeTest",
- "android.assist.cts.LargeViewHierarchyTest",
- "android.assist.cts.ScreenshotTest",
- "android.assist.cts.TextViewTest",
- "android.assist.cts.WebViewTest"
- ],
- bug: 21668302
-},
-{
description: "ConnectivityConstraintTest job scheduler not working.",
names: [
"android.jobscheduler.cts.ConnectivityConstraintTest#testConnectivityConstraintExecutes_withWifi",
diff --git a/tests/tests/animation/Android.mk b/tests/tests/animation/Android.mk
index 205adda..ed42d74 100644
--- a/tests/tests/animation/Android.mk
+++ b/tests/tests/animation/Android.mk
@@ -24,13 +24,19 @@
# When built, explicitly put it in the data partition.
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES += \
+ android-support-test \
+ mockito-target \
+ android-common \
+ ctsdeviceutil \
+ ctstestrunner \
+ platform-test-annotations
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_SRC_FILES := $(call all-java-files-under, src)
# Tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts
-LOCAL_SDK_VERSION := current
-
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/animation/src/android/animation/cts/AnimatorListenerAdapterTest.java b/tests/tests/animation/src/android/animation/cts/AnimatorListenerAdapterTest.java
new file mode 100644
index 0000000..c6c0bc4
--- /dev/null
+++ b/tests/tests/animation/src/android/animation/cts/AnimatorListenerAdapterTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+package android.animation.cts;
+
+import android.animation.AnimatorListenerAdapter;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+
+@SmallTest
+public class AnimatorListenerAdapterTest {
+ /**
+ * AnimatorListenerAdapter has a noop implementation of the AnimatorListener interface.
+ * It should do nothing, including when nulls are passed to it.
+ * <p>
+ * Mostly this test pokes the implementation so that it is counted as tested. There isn't
+ * much to test here since it has no implementation.
+ */
+ @Test
+ public void testNullOk() throws Throwable {
+ AnimatorListenerAdapter adapter = new MyAdapter();
+ adapter.onAnimationStart(null);
+ adapter.onAnimationEnd(null);
+ adapter.onAnimationRepeat(null);
+ adapter.onAnimationCancel(null);
+ adapter.onAnimationPause(null);
+ adapter.onAnimationResume(null);
+ }
+
+ private static class MyAdapter extends AnimatorListenerAdapter {
+ }
+}
diff --git a/tests/tests/animation/src/android/animation/cts/AnimatorSetTest.java b/tests/tests/animation/src/android/animation/cts/AnimatorSetTest.java
index 3bf86de..77b1583 100644
--- a/tests/tests/animation/src/android/animation/cts/AnimatorSetTest.java
+++ b/tests/tests/animation/src/android/animation/cts/AnimatorSetTest.java
@@ -438,6 +438,82 @@
assertSame(animator2.getInterpolator(), clone2.getInterpolator());
}
+ public void testSetSynchronized() throws Throwable {
+ final TargetObj obj1 = new TargetObj();
+ final TargetObj obj2 = new TargetObj();
+ ObjectAnimator anim1 = ObjectAnimator.ofFloat(obj1, "val", 0, 1);
+ ObjectAnimator anim2 = ObjectAnimator.ofFloat(obj1, "val", 0, 1);
+ ObjectAnimator anim3 = ObjectAnimator.ofFloat(obj1, "val", 0, 1);
+ anim1.setStartDelay(100);
+ anim2.setStartDelay(400);
+ anim3.setStartDelay(700);
+ final AnimatorSet combined1 = new AnimatorSet();
+ combined1.playTogether(anim1, anim2, anim3);
+
+ ObjectAnimator anim4 = ObjectAnimator.ofFloat(obj2, "val", 0, 1);
+ ObjectAnimator anim5 = ObjectAnimator.ofFloat(obj2, "val", 0, 1);
+ ObjectAnimator anim6 = ObjectAnimator.ofFloat(obj2, "val", 0, 1);
+ final AnimatorSet combined2 = new AnimatorSet();
+ combined2.playSequentially(anim4, anim5, anim6);
+ combined2.setStartDelay(100);
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ combined1.start();
+ combined2.start();
+ }
+ });
+
+ while (combined1.isRunning()) {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(obj1.value, obj2.value);
+ }
+ });
+ }
+ }
+
+ public void testNotifiesAfterEnd() throws Throwable {
+ final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
+ Animator.AnimatorListener listener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ assertTrue(animation.isStarted());
+ assertTrue(animation.isRunning());
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ assertFalse(animation.isRunning());
+ assertFalse(animation.isStarted());
+ super.onAnimationEnd(animation);
+ }
+ };
+ animator.addListener(listener);
+ final AnimatorSet animatorSet = new AnimatorSet();
+ animatorSet.playTogether(animator);
+ animatorSet.addListener(listener);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ animatorSet.start();
+ animator.end();
+ assertFalse(animator.isStarted());
+ assertFalse(animatorSet.isStarted());
+ }
+ });
+ }
+
+ static class TargetObj {
+ public float value = 0;
+
+ public void setVal(float value) {
+ this.value = value;
+ }
+ }
+
class AnimateObject {
int x = 1;
int y = 2;
diff --git a/tests/tests/animation/src/android/animation/cts/EvaluatorTest.java b/tests/tests/animation/src/android/animation/cts/EvaluatorTest.java
index 0812351..9c90f40 100644
--- a/tests/tests/animation/src/android/animation/cts/EvaluatorTest.java
+++ b/tests/tests/animation/src/android/animation/cts/EvaluatorTest.java
@@ -27,10 +27,12 @@
import android.graphics.PointF;
import android.graphics.Rect;
import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
/**
* Tests for the various Evaluator classes in android.animation
*/
+@SmallTest
public class EvaluatorTest extends InstrumentationTestCase {
public void testFloatEvaluator() {
@@ -50,10 +52,18 @@
}
public void testFloatArrayEvaluator() {
+ FloatArrayEvaluator evaluator = new FloatArrayEvaluator();
+ floatArrayEvaluatorTestImpl(evaluator, null);
+
+ float[] reusableArray = new float[2];
+ FloatArrayEvaluator evaluator2 = new FloatArrayEvaluator(reusableArray);
+ floatArrayEvaluatorTestImpl(evaluator2, reusableArray);
+ }
+
+ private void floatArrayEvaluatorTestImpl(FloatArrayEvaluator evaluator, float[] reusedArray) {
float[] start = {0f, 0f};
float[] end = {.8f, 1.0f};
float fraction = 0.5f;
- FloatArrayEvaluator evaluator = new FloatArrayEvaluator();
float[] result = evaluator.evaluate(0, start, end);
assertEquals(start[0], result[0], .001f);
@@ -66,51 +76,63 @@
result = evaluator.evaluate(1, start, end);
assertEquals(end[0], result[0], .001f);
assertEquals(end[1], result[1], .001f);
+
+ if (reusedArray != null) {
+ assertEquals(reusedArray, result);
+ }
}
public void testArgbEvaluator() throws Throwable {
- final int RED = 0xffFF8080;
- final int BLUE = 0xff8080FF;
- int aRED = Color.alpha(RED);
- int rRED = Color.red(RED);
- int gRED = Color.green(RED);
- int bRED = Color.blue(RED);
- int aBLUE = Color.alpha(BLUE);
- int rBLUE = Color.red(BLUE);
- int gBLUE = Color.green(BLUE);
- int bBLUE = Color.blue(BLUE);
+ final int START = 0xffFF8080;
+ final int END = 0xff8080FF;
+ int aSTART = Color.alpha(START);
+ int rSTART = Color.red(START);
+ int gSTART = Color.green(START);
+ int bSTART = Color.blue(START);
+ int aEND = Color.alpha(END);
+ int rEND = Color.red(END);
+ int gEND = Color.green(END);
+ int bEND = Color.blue(END);
final ArgbEvaluator evaluator = new ArgbEvaluator();
- int result = (Integer) evaluator.evaluate(0, RED, BLUE);
+ int result = (Integer) evaluator.evaluate(0, START, END);
int aResult = Color.alpha(result);
int rResult = Color.red(result);
int gResult = Color.green(result);
int bResult = Color.blue(result);
- assertEquals(aRED, aResult);
- assertEquals(rRED, rResult);
- assertEquals(gRED, gResult);
- assertEquals(bRED, bResult);
+ assertEquals(aSTART, aResult);
+ assertEquals(rSTART, rResult);
+ assertEquals(gSTART, gResult);
+ assertEquals(bSTART, bResult);
- result = (Integer) evaluator.evaluate(.5f, RED, BLUE);
+ result = (Integer) evaluator.evaluate(.5f, START, END);
aResult = Color.alpha(result);
rResult = Color.red(result);
gResult = Color.green(result);
bResult = Color.blue(result);
assertEquals(0xff, aResult);
- assertEquals(rRED + (int)(.5f * (rBLUE - rRED)), rResult);
- assertEquals(gRED + (int)(.5f * (gBLUE - gRED)), gResult);
- assertEquals(bRED + (int)(.5f * (bBLUE - bRED)), bResult);
+ assertEquals(0x80, gResult);
+ if (rSTART < rEND) {
+ assertTrue(rResult > rSTART && rResult < rEND);
+ } else {
+ assertTrue(rResult < rSTART && rResult > rEND);
+ }
+ if (bSTART < bEND) {
+ assertTrue(bResult > bSTART && bResult < bEND);
+ } else {
+ assertTrue(bResult < bSTART && bResult > bEND);
+ }
- result = (Integer) evaluator.evaluate(1, RED, BLUE);
+ result = (Integer) evaluator.evaluate(1, START, END);
aResult = Color.alpha(result);
rResult = Color.red(result);
gResult = Color.green(result);
bResult = Color.blue(result);
- assertEquals(aBLUE, aResult);
- assertEquals(rBLUE, rResult);
- assertEquals(gBLUE, gResult);
- assertEquals(bBLUE, bResult);
+ assertEquals(aEND, aResult);
+ assertEquals(rEND, rResult);
+ assertEquals(gEND, gResult);
+ assertEquals(bEND, bResult);
}
public void testIntEvaluator() throws Throwable {
@@ -130,10 +152,18 @@
}
public void testIntArrayEvaluator() {
+ IntArrayEvaluator evaluator = new IntArrayEvaluator();
+ intArrayEvaluatorTestImpl(evaluator, null);
+
+ int[] reusableArray = new int[2];
+ IntArrayEvaluator evaluator2 = new IntArrayEvaluator(reusableArray);
+ intArrayEvaluatorTestImpl(evaluator2, reusableArray);
+ }
+
+ private void intArrayEvaluatorTestImpl(IntArrayEvaluator evaluator, int[] reusedArray) {
int[] start = {0, 0};
int[] end = {80, 100};
float fraction = 0.5f;
- IntArrayEvaluator evaluator = new IntArrayEvaluator();
int[] result = evaluator.evaluate(0, start, end);
assertEquals(start[0], result[0]);
@@ -146,10 +176,22 @@
result = evaluator.evaluate(1, start, end);
assertEquals(end[0], result[0]);
assertEquals(end[1], result[1]);
+
+ if (reusedArray != null) {
+ assertEquals(reusedArray, result);
+ }
}
public void testRectEvaluator() throws Throwable {
final RectEvaluator evaluator = new RectEvaluator();
+ rectEvaluatorTestImpl(evaluator, null);
+
+ Rect reusableRect = new Rect();
+ final RectEvaluator evaluator2 = new RectEvaluator(reusableRect);
+ rectEvaluatorTestImpl(evaluator2, reusableRect);
+ }
+
+ private void rectEvaluatorTestImpl(RectEvaluator evaluator, Rect reusedRect) {
final Rect start = new Rect(0, 0, 0, 0);
final Rect end = new Rect(100, 200, 300, 400);
final float fraction = 0.5f;
@@ -171,10 +213,22 @@
assertEquals(end.top, result.top, .001f);
assertEquals(end.right, result.right, .001f);
assertEquals(end.bottom, result.bottom, .001f);
+
+ if (reusedRect != null) {
+ assertEquals(reusedRect, result);
+ }
}
public void testPointFEvaluator() throws Throwable {
final PointFEvaluator evaluator = new PointFEvaluator();
+ pointFEvaluatorTestImpl(evaluator, null);
+
+ PointF reusablePoint = new PointF();
+ final PointFEvaluator evaluator2 = new PointFEvaluator(reusablePoint);
+ pointFEvaluatorTestImpl(evaluator2, reusablePoint);
+ }
+
+ private void pointFEvaluatorTestImpl(PointFEvaluator evaluator, PointF reusedPoint) {
final PointF start = new PointF(0, 0);
final PointF end = new PointF(100, 200);
final float fraction = 0.5f;
@@ -190,6 +244,10 @@
result = evaluator.evaluate(1, start, end);
assertEquals(end.x, result.x, .001f);
assertEquals(end.y, result.y, .001f);
+
+ if (reusedPoint != null) {
+ assertEquals(reusedPoint, result);
+ }
}
/**
diff --git a/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java b/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
index 6ff1cf9..a96b8c9 100644
--- a/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
+++ b/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
@@ -16,17 +16,39 @@
package android.animation.cts;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
+import android.animation.TypeConverter;
import android.animation.ValueAnimator;
+import android.graphics.Color;
+import android.graphics.Path;
+import android.graphics.PointF;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Property;
+import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Interpolator;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
public class ObjectAnimatorTest extends
ActivityInstrumentationTestCase2<AnimationActivity> {
+ private static final float LINE1_START = -32f;
+ private static final float LINE1_END = -2f;
+ private static final float LINE1_Y = 0f;
+ private static final float LINE2_START = 2f;
+ private static final float LINE2_END = 12f;
+ private static final float QUADRATIC_CTRL_PT1_X = 0f;
+ private static final float QUADRATIC_CTRL_PT1_Y = 0f;
+ private static final float QUADRATIC_CTRL_PT2_X = 50f;
+ private static final float QUADRATIC_CTRL_PT2_Y = 20f;
+ private static final float QUADRATIC_CTRL_PT3_X = 100f;
+ private static final float QUADRATIC_CTRL_PT3_Y = 0f;
+
private AnimationActivity mActivity;
private ObjectAnimator mObjectAnimator;
private long mDuration = 1000;
@@ -162,6 +184,59 @@
assertTrue(endColor <= i.intValue());
}
+ public void testOfArgb() throws Throwable {
+ Object object = mActivity.view;
+ String property = "backgroundColor";
+ int start = 0xffff0000;
+ int end = 0xff0000ff;
+ int[] values = {start, end};
+ int startRed = Color.red(start);
+ int startBlue = Color.blue(start);
+ int endRed = Color.red(end);
+ int endBlue = Color.blue(end);
+ final ObjectAnimator animator = ObjectAnimator.ofArgb(object, property, start, end);
+ animator.setDuration(mDuration);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ if (animation.getAnimatedFraction() > .05f) {
+ latch.countDown();
+ }
+ }
+ });
+
+ this.runTestOnUiThread(new Runnable(){
+ public void run() {
+ animator.start();
+ }
+ });
+ boolean isRunning = animator.isRunning();
+ assertTrue(isRunning);
+
+ assertTrue(latch.await(500, TimeUnit.MILLISECONDS));
+
+ Integer animatedValue = (Integer) animator.getAnimatedValue();
+ int alpha = Color.alpha(animatedValue);
+ int red = Color.red(animatedValue);
+ int green = Color.green(animatedValue);
+ int blue = Color.blue(animatedValue);
+ assertTrue(red < startRed);
+ assertTrue(red > endRed);
+ assertTrue(blue > startBlue);
+ assertTrue(blue < endBlue);
+ assertEquals(255, alpha);
+ assertEquals(0, green);
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ animator.cancel();
+ }
+ });
+ }
+
public void testGetPropertyName() throws Throwable {
Object object = mActivity.view.newBall;
String propertyName = "backgroundColor";
@@ -230,6 +305,473 @@
assertEquals(interpolator, cloneAnimator.getInterpolator());
}
+ public void testOfFloat_Path() throws Throwable {
+ // Test for ObjectAnimator.ofFloat(Object, String, String, Path)
+ // Create a path that contains two disconnected line segments. Check that the animated
+ // property x and property y always stay on the line segments.
+ Path path = new Path();
+ path.moveTo(LINE1_START, LINE1_Y);
+ path.lineTo(LINE1_END, LINE1_Y);
+ path.moveTo(LINE2_START, LINE2_START);
+ path.lineTo(LINE2_END, LINE2_END);
+ final double totalLength = (LINE1_END - LINE1_START) + Math.sqrt(
+ (LINE2_END - LINE2_START) * (LINE2_END - LINE2_START) +
+ (LINE2_END - LINE2_START) * (LINE2_END - LINE2_START));
+ final double firstSegEndFraction = (LINE1_END - LINE1_START) / totalLength;
+ final float delta = 0.01f;
+
+ Object target = new Object() {
+ public void setX(float x) {
+ }
+
+ public void setY(float y) {
+ }
+ };
+ final CountDownLatch endLatch = new CountDownLatch(1);
+
+ final ObjectAnimator anim = ObjectAnimator.ofFloat(target, "x", "y", path);
+ anim.setDuration(200);
+ // Linear interpolator
+ anim.setInterpolator(null);
+ anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float fraction = animation.getAnimatedFraction();
+ float x = (Float) animation.getAnimatedValue("x");
+ float y = (Float) animation.getAnimatedValue("y");
+
+ // Check that the point is on the path.
+ if (x <= 0) {
+ // First line segment is a horizontal line.
+ assertTrue(x >= LINE1_START);
+ assertTrue(x <= LINE1_END);
+ assertEquals(LINE1_Y, y);
+
+ // Check that the time animation stays on the first segment is proportional to
+ // the length of the first line segment.
+ assertTrue(fraction < firstSegEndFraction + delta);
+ } else {
+ assertTrue(x >= LINE2_START);
+ assertTrue(x <= LINE2_END);
+ assertEquals(x, y);
+
+ // Check that the time animation stays on the second segment is proportional to
+ // the length of the second line segment.
+ assertTrue(fraction > firstSegEndFraction - delta);
+ }
+ }
+ });
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim.start();
+ }
+ });
+ assertTrue(endLatch.await(400, TimeUnit.MILLISECONDS));
+ }
+
+ public void testOfInt_Path() throws Throwable {
+ // Test for ObjectAnimator.ofInt(Object, String, String, Path)
+ // Create a path that contains two disconnected line segments. Check that the animated
+ // property x and property y always stay on the line segments.
+ Path path = new Path();
+ path.moveTo(LINE1_START, -LINE1_START);
+ path.lineTo(LINE1_END, -LINE1_END);
+ path.moveTo(LINE2_START, LINE2_START);
+ path.lineTo(LINE2_END, LINE2_END);
+
+ Object target = new Object() {
+ public void setX(float x) {
+ }
+
+ public void setY(float y) {
+ }
+ };
+ final CountDownLatch endLatch = new CountDownLatch(1);
+ final ObjectAnimator anim = ObjectAnimator.ofInt(target, "x", "y", path);
+ anim.setDuration(200);
+
+ // Linear interpolator
+ anim.setInterpolator(null);
+ anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float fraction = animation.getAnimatedFraction();
+ int x = (Integer) animation.getAnimatedValue("x");
+ int y = (Integer) animation.getAnimatedValue("y");
+
+ // Check that the point is on the path.
+ if (x <= 0) {
+ // Check that the time animation stays on the first segment is proportional to
+ // the length of the first line segment.
+ assertTrue(x >= LINE1_START);
+ assertTrue(x <= LINE1_END);
+ assertEquals(x, -y);
+
+ // First line segment is 3 times as long as the second line segment, so the
+ // 3/4 of the animation duration will be spent on the first line segment.
+ assertTrue(fraction <= 0.75f);
+ } else {
+ // Check that the time animation stays on the second segment is proportional to
+ // the length of the second line segment.
+ assertTrue(x >= LINE2_START);
+ assertTrue(x <= LINE2_END);
+ assertEquals(x, y);
+
+ assertTrue(fraction >= 0.75f);
+ }
+ }
+ });
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim.start();
+ }
+ });
+ assertTrue(endLatch.await(400, TimeUnit.MILLISECONDS));
+
+ }
+
+ public void testOfMultiFloat_Path() throws Throwable {
+ // Test for ObjectAnimator.ofMultiFloat(Object, String, Path);
+ // Create a quadratic bezier curve that are symmetric about the vertical line (x = 50).
+ // Expect when fraction < 0.5, x < 50, otherwise, x >= 50.
+ Path path = new Path();
+ path.moveTo(QUADRATIC_CTRL_PT1_X, QUADRATIC_CTRL_PT1_Y);
+ path.quadTo(QUADRATIC_CTRL_PT2_X, QUADRATIC_CTRL_PT2_Y,
+ QUADRATIC_CTRL_PT3_X, QUADRATIC_CTRL_PT3_Y);
+
+ Object target = new Object() {
+ public void setPosition(float x, float y) {
+ }
+ };
+
+ final CountDownLatch endLatch = new CountDownLatch(1);
+ final ObjectAnimator anim = ObjectAnimator.ofMultiFloat(target, "position", path);
+ // Linear interpolator
+ anim.setInterpolator(null);
+ anim.setDuration(200);
+
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+
+ anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ float lastFraction = 0;
+ float lastX = 0;
+ float lastY = 0;
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float[] values = (float[]) animation.getAnimatedValue();
+ assertEquals(2, values.length);
+ float x = values[0];
+ float y = values[1];
+ float fraction = animation.getAnimatedFraction();
+ // Given that the curve is symmetric about the line (x = 50), x should be less than
+ // 50 for half of the animation duration.
+ if (fraction < 0.5) {
+ assertTrue(x < QUADRATIC_CTRL_PT2_X);
+ } else {
+ assertTrue(x >= QUADRATIC_CTRL_PT2_X);
+ }
+
+ if (lastFraction > 0.5) {
+ // x should be increasing, y should be decreasing
+ assertTrue(x >= lastX);
+ assertTrue(y <= lastY);
+ } else if (fraction <= 0.5) {
+ // when fraction <= 0.5, both x, y should be increasing
+ assertTrue(x >= lastX);
+ assertTrue(y >= lastY);
+ }
+ lastX = x;
+ lastY = y;
+ lastFraction = fraction;
+ }
+ });
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim.start();
+ }
+ });
+ assertTrue(endLatch.await(400, TimeUnit.MILLISECONDS));
+ }
+
+ public void testOfMultiFloat() throws Throwable {
+ // Test for ObjectAnimator.ofMultiFloat(Object, String, float[][]);
+ final float[][] data = new float[10][];
+ for (int i = 0; i < data.length; i++) {
+ data[i] = new float[3];
+ data[i][0] = i;
+ data[i][1] = i * 2;
+ data[i][2] = 0f;
+ }
+
+ Object target = new Object() {
+ public void setPosition(float x, float y, float z) {
+ }
+ };
+ final CountDownLatch endLatch = new CountDownLatch(1);
+ final ObjectAnimator anim = ObjectAnimator.ofMultiFloat(target, "position", data);
+ anim.setInterpolator(null);
+ anim.setDuration(60);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+
+ anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float fraction = animation.getAnimatedFraction();
+ float[] values = (float[]) animation.getAnimatedValue();
+ assertEquals(3, values.length);
+
+ float expectedX = fraction * (data.length - 1);
+
+ assertEquals(expectedX, values[0]);
+ assertEquals(expectedX * 2, values[1]);
+ assertEquals(0f, values[2]);
+ }
+ });
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim.start();
+ }
+ });
+ assertTrue(endLatch.await(200, TimeUnit.MILLISECONDS));
+ }
+
+ public void testOfMultiInt_Path() throws Throwable {
+ // Test for ObjectAnimator.ofMultiInt(Object, String, Path);
+ // Create a quadratic bezier curve that are symmetric about the vertical line (x = 50).
+ // Expect when fraction < 0.5, x < 50, otherwise, x >= 50.
+ Path path = new Path();
+ path.moveTo(QUADRATIC_CTRL_PT1_X, QUADRATIC_CTRL_PT1_Y);
+ path.quadTo(QUADRATIC_CTRL_PT2_X, QUADRATIC_CTRL_PT2_Y,
+ QUADRATIC_CTRL_PT3_X, QUADRATIC_CTRL_PT3_Y);
+
+ Object target = new Object() {
+ public void setPosition(int x, int y) {
+ }
+ };
+
+ final CountDownLatch endLatch = new CountDownLatch(1);
+ final ObjectAnimator anim = ObjectAnimator.ofMultiInt(target, "position", path);
+ // Linear interpolator
+ anim.setInterpolator(null);
+ anim.setDuration(200);
+
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+
+ anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ float lastFraction = 0;
+ int lastX = 0;
+ int lastY = 0;
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ int[] values = (int[]) animation.getAnimatedValue();
+ assertEquals(2, values.length);
+ int x = values[0];
+ int y = values[1];
+ float fraction = animation.getAnimatedFraction();
+ // Given that the curve is symmetric about the line (x = 50), x should be less than
+ // 50 for half of the animation duration.
+ if (fraction < 0.5) {
+ assertTrue(x < QUADRATIC_CTRL_PT2_X);
+ } else {
+ assertTrue(x >= QUADRATIC_CTRL_PT2_X);
+ }
+
+ if (lastFraction > 0.5) {
+ // x should be increasing, y should be decreasing
+ assertTrue(x >= lastX);
+ assertTrue(y <= lastY);
+ } else if (fraction <= 0.5) {
+ // when fraction <= 0.5, both x, y should be increasing
+ assertTrue(x >= lastX);
+ assertTrue(y >= lastY);
+ }
+ lastX = x;
+ lastY = y;
+ lastFraction = fraction;
+ }
+ });
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim.start();
+ }
+ });
+ assertTrue(endLatch.await(400, TimeUnit.MILLISECONDS));
+ }
+
+ public void testOfMultiInt() throws Throwable {
+ // Test for ObjectAnimator.ofMultiFloat(Object, String, int[][]);
+ final int[][] data = new int[10][];
+ for (int i = 0; i < data.length; i++) {
+ data[i] = new int[3];
+ data[i][0] = i;
+ data[i][1] = i * 2;
+ data[i][2] = 0;
+ }
+
+ Object target = new Object() {
+ public void setPosition(int x, int y, int z) {
+ }
+ };
+ final CountDownLatch endLatch = new CountDownLatch(1);
+ final ObjectAnimator anim = ObjectAnimator.ofMultiInt(target, "position", data);
+ anim.setInterpolator(null);
+ anim.setDuration(60);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+
+ anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float fraction = animation.getAnimatedFraction();
+ int[] values = (int[]) animation.getAnimatedValue();
+ assertEquals(3, values.length);
+
+ int expectedX = Math.round(fraction * (data.length - 1));
+ int expectedY = Math.round(fraction * (data.length - 1) * 2);
+
+ // Allow a delta of 1 for rounding errors.
+ assertEquals(expectedX, values[0], 1);
+ assertEquals(expectedY, values[1], 1);
+ assertEquals(0, values[2]);
+ }
+ });
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim.start();
+ }
+ });
+ assertTrue(endLatch.await(200, TimeUnit.MILLISECONDS));
+ }
+
+ public void testOfObject_Converter() throws Throwable {
+ // Test for ObjectAnimator.ofObject(Object, String, TypeConverter<T, V>, Path)
+ // Create a path that contains two disconnected line segments. Check that the animated
+ // property x and property y always stay on the line segments.
+ Path path = new Path();
+ path.moveTo(LINE1_START, -LINE1_START);
+ path.lineTo(LINE1_END, -LINE1_END);
+ path.moveTo(LINE2_START, LINE2_START);
+ path.lineTo(LINE2_END, LINE2_END);
+
+ Object target1 = new Object() {
+ public void setDistance(float distance) {
+ }
+ };
+ Object target2 = new Object() {
+ public void setPosition(PointF pos) {
+ }
+ };
+ TypeConverter<PointF, Float> converter = new TypeConverter<PointF, Float>(
+ PointF.class, Float.class) {
+ @Override
+ public Float convert(PointF value) {
+ return (float) Math.sqrt(value.x * value.x + value.y * value.y);
+ }
+ };
+ final CountDownLatch endLatch = new CountDownLatch(2);
+
+ // Create two animators. One use a converter that converts the point to distance to origin.
+ // The other one does not have a type converter.
+ final ObjectAnimator anim1 = ObjectAnimator.ofObject(target1, "distance", converter, path);
+ anim1.setDuration(100);
+ anim1.setInterpolator(null);
+ anim1.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+
+ final ObjectAnimator anim2 = ObjectAnimator.ofObject(target2, "position", null, path);
+ anim2.setDuration(100);
+ anim2.setInterpolator(null);
+ anim2.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+ anim2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ // Set the initial value of the distance to the distance between the first point on
+ // the path to the origin.
+ float mLastDistance = (float) (32 * Math.sqrt(2));
+ float mLastFraction = 0f;
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float fraction = anim1.getAnimatedFraction();
+ assertEquals(fraction, anim2.getAnimatedFraction());
+ float distance = (Float) anim1.getAnimatedValue();
+ PointF position = (PointF) anim2.getAnimatedValue();
+
+ // Manually calculate the distance for the animator that doesn't have a
+ // TypeConverter, and expect the result to be the same as the animation value from
+ // the type converter.
+ float distanceFromPosition = (float) Math.sqrt(
+ position.x * position.x + position.y * position.y);
+ assertEquals(distance, distanceFromPosition, 0.0001f);
+
+ if (mLastFraction > 0.75) {
+ // In the 2nd line segment of the path, distance to origin should be increasing.
+ assertTrue(distance >= mLastDistance);
+ } else if (fraction < 0.75) {
+ assertTrue(distance <= mLastDistance);
+ }
+ mLastDistance = distance;
+ mLastFraction = fraction;
+ }
+ });
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim1.start();
+ anim2.start();
+ }
+ });
+
+ // Wait until both of the animations finish
+ assertTrue(endLatch.await(200, TimeUnit.MILLISECONDS));
+ }
+
public void testIsStarted() throws Throwable {
Object object = mActivity.view.newBall;
String property = "y";
@@ -308,6 +850,46 @@
});
}
+ public void testCachedValues() throws Throwable {
+ final AnimTarget target = new AnimTarget();
+ final ObjectAnimator anim = ObjectAnimator.ofFloat(target, "testValue", 100);
+ anim.setDuration(200);
+ final CountDownLatch twoFramesLatch = new CountDownLatch(2);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim.start();
+ final View decor = getActivity().getWindow().getDecorView();
+ decor.postOnAnimation(new Runnable() {
+ @Override
+ public void run() {
+ if (twoFramesLatch.getCount() > 0) {
+ twoFramesLatch.countDown();
+ decor.postOnAnimation(this);
+ }
+ }
+ });
+ }
+ });
+
+ assertTrue("Animation didn't start in a reasonable time",
+ twoFramesLatch.await(100, TimeUnit.MILLISECONDS));
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue("Start value should readjust to current position",
+ target.getTestValue() != 0);
+ anim.cancel();
+ anim.setupStartValues();
+ anim.start();
+ assertTrue("Start value should readjust to current position",
+ target.getTestValue() != 0);
+ anim.cancel();
+ }
+ });
+ }
+
static class AnimTarget {
private float mTestValue = 0;
diff --git a/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java b/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java
index 200ebce..5e23b29 100644
--- a/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java
+++ b/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java
@@ -21,9 +21,14 @@
import android.animation.Keyframe;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
+import android.animation.TypeConverter;
import android.animation.ValueAnimator;
+import android.graphics.Color;
+import android.graphics.Path;
+import android.graphics.PointF;
import android.graphics.drawable.ShapeDrawable;
import android.test.ActivityInstrumentationTestCase2;
+import android.util.FloatProperty;
import android.util.Property;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
@@ -33,6 +38,18 @@
public class PropertyValuesHolderTest extends
ActivityInstrumentationTestCase2<AnimationActivity> {
+ private static final float LINE1_START = -32f;
+ private static final float LINE1_END = -2f;
+ private static final float LINE1_Y = 0f;
+ private static final float LINE2_START = 2f;
+ private static final float LINE2_END = 12f;
+ private static final float QUADRATIC_CTRL_PT1_X = 0f;
+ private static final float QUADRATIC_CTRL_PT1_Y = 0f;
+ private static final float QUADRATIC_CTRL_PT2_X = 50f;
+ private static final float QUADRATIC_CTRL_PT2_Y = 20f;
+ private static final float QUADRATIC_CTRL_PT3_X = 100f;
+ private static final float QUADRATIC_CTRL_PT3_Y = 0f;
+
private AnimationActivity mActivity;
private Animator mAnimator;
private long mDuration = 1000;
@@ -199,7 +216,7 @@
assertEquals("Animation should run as expected", 100f, mActivity.view.newBall.getY());
}
- public void testOffloat() throws Throwable {
+ public void testOfFloat() throws Throwable {
float[] values = {mStartY, mEndY};
PropertyValuesHolder pVHolder = PropertyValuesHolder.ofFloat(mProperty, values);
assertNotNull(pVHolder);
@@ -272,10 +289,425 @@
mDuration);
startAnimation(objectAnimator, colorAnimator);
Thread.sleep(1000);
- Integer i = (Integer) colorAnimator.getAnimatedValue();
- //We are going from less negative value to a more negative value
- assertTrue(i.intValue() <= startColor);
- assertTrue(endColor <= i.intValue());
+ Integer animatedValue = (Integer) colorAnimator.getAnimatedValue();
+ int redMin = Math.min(Color.red(startColor), Color.red(endColor));
+ int redMax = Math.max(Color.red(startColor), Color.red(endColor));
+ int blueMin = Math.min(Color.blue(startColor), Color.blue(endColor));
+ int blueMax = Math.max(Color.blue(startColor), Color.blue(endColor));
+ assertTrue(Color.red(animatedValue) >= redMin);
+ assertTrue(Color.red(animatedValue) <= redMax);
+ assertTrue(Color.blue(animatedValue) >= blueMin);
+ assertTrue(Color.blue(animatedValue) <= blueMax);
+ }
+
+ public void testOfMultiFloat_Path() throws Throwable {
+ // Test for PropertyValuesHolder.ofMultiFloat(String, Path);
+ // Create a quadratic bezier curve that are symmetric about the vertical line (x = 50).
+ // Expect when fraction < 0.5, x < 50, otherwise, x >= 50.
+ Path path = new Path();
+ path.moveTo(QUADRATIC_CTRL_PT1_X, QUADRATIC_CTRL_PT1_Y);
+ path.quadTo(QUADRATIC_CTRL_PT2_X, QUADRATIC_CTRL_PT2_Y,
+ QUADRATIC_CTRL_PT3_X, QUADRATIC_CTRL_PT3_Y);
+
+ PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiFloat("position", path);
+ final ValueAnimator anim = ValueAnimator.ofPropertyValuesHolder(pvh);
+
+ final CountDownLatch endLatch = new CountDownLatch(1);
+ // Linear interpolator
+ anim.setInterpolator(null);
+ anim.setDuration(200);
+
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+
+ anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ float lastFraction = 0;
+ float lastX = 0;
+ float lastY = 0;
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float[] values = (float[]) animation.getAnimatedValue();
+ assertEquals(2, values.length);
+ float x = values[0];
+ float y = values[1];
+ float fraction = animation.getAnimatedFraction();
+ // Given that the curve is symmetric about the line (x = 50), x should be less than
+ // 50 for half of the animation duration.
+ if (fraction < 0.5) {
+ assertTrue(x < QUADRATIC_CTRL_PT2_X);
+ } else {
+ assertTrue(x >= QUADRATIC_CTRL_PT2_X);
+ }
+
+ if (lastFraction > 0.5) {
+ // x should be increasing, y should be decreasing
+ assertTrue(x >= lastX);
+ assertTrue(y <= lastY);
+ } else if (fraction <= 0.5) {
+ // when fraction <= 0.5, both x, y should be increasing
+ assertTrue(x >= lastX);
+ assertTrue(y >= lastY);
+ }
+ lastX = x;
+ lastY = y;
+ lastFraction = fraction;
+ }
+ });
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim.start();
+ }
+ });
+ assertTrue(endLatch.await(400, TimeUnit.MILLISECONDS));
+ }
+
+ public void testOfMultiFloat_Array() throws Throwable {
+ // Test for PropertyValuesHolder.ofMultiFloat(String, float[][]);
+ final float[][] data = new float[10][];
+ for (int i = 0; i < data.length; i++) {
+ data[i] = new float[3];
+ data[i][0] = i;
+ data[i][1] = i * 2;
+ data[i][2] = 0f;
+ }
+ final CountDownLatch endLatch = new CountDownLatch(1);
+ final PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiFloat("position", data);
+
+ final ValueAnimator anim = ValueAnimator.ofPropertyValuesHolder(pvh);
+ anim.setInterpolator(null);
+ anim.setDuration(60);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+
+ anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float fraction = animation.getAnimatedFraction();
+ float[] values = (float[]) animation.getAnimatedValue();
+ assertEquals(3, values.length);
+
+ float expectedX = fraction * (data.length - 1);
+
+ assertEquals(expectedX, values[0]);
+ assertEquals(expectedX * 2, values[1]);
+ assertEquals(0f, values[2]);
+ }
+ });
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim.start();
+ }
+ });
+ assertTrue(endLatch.await(200, TimeUnit.MILLISECONDS));
+ }
+
+ public void testOfMultiInt_Path() throws Throwable {
+ // Test for PropertyValuesHolder.ofMultiInt(String, Path);
+ // Create a quadratic bezier curve that are symmetric about the vertical line (x = 50).
+ // Expect when fraction < 0.5, x < 50, otherwise, x >= 50.
+ Path path = new Path();
+ path.moveTo(QUADRATIC_CTRL_PT1_X, QUADRATIC_CTRL_PT1_Y);
+ path.quadTo(QUADRATIC_CTRL_PT2_X, QUADRATIC_CTRL_PT2_Y,
+ QUADRATIC_CTRL_PT3_X, QUADRATIC_CTRL_PT3_Y);
+
+ final CountDownLatch endLatch = new CountDownLatch(1);
+ final PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiInt("position", path);
+ final ValueAnimator anim = ValueAnimator.ofPropertyValuesHolder(pvh);
+ // Linear interpolator
+ anim.setInterpolator(null);
+ anim.setDuration(200);
+
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+
+ anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ float lastFraction = 0;
+ int lastX = 0;
+ int lastY = 0;
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ int[] values = (int[]) animation.getAnimatedValue();
+ assertEquals(2, values.length);
+ int x = values[0];
+ int y = values[1];
+ float fraction = animation.getAnimatedFraction();
+ // Given that the curve is symmetric about the line (x = 50), x should be less than
+ // 50 for half of the animation duration.
+ if (fraction < 0.5) {
+ assertTrue(x < QUADRATIC_CTRL_PT2_X);
+ } else {
+ assertTrue(x >= QUADRATIC_CTRL_PT2_X);
+ }
+
+ if (lastFraction > 0.5) {
+ // x should be increasing, y should be decreasing
+ assertTrue(x >= lastX);
+ assertTrue(y <= lastY);
+ } else if (fraction <= 0.5) {
+ // when fraction <= 0.5, both x, y should be increasing
+ assertTrue(x >= lastX);
+ assertTrue(y >= lastY);
+ }
+ lastX = x;
+ lastY = y;
+ lastFraction = fraction;
+ }
+ });
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim.start();
+ }
+ });
+ assertTrue(endLatch.await(400, TimeUnit.MILLISECONDS));
+ }
+
+ public void testOfMultiInt_Array() throws Throwable {
+ // Test for PropertyValuesHolder.ofMultiFloat(String, int[][]);
+ final int[][] data = new int[10][];
+ for (int i = 0; i < data.length; i++) {
+ data[i] = new int[3];
+ data[i][0] = i;
+ data[i][1] = i * 2;
+ data[i][2] = 0;
+ }
+
+ final CountDownLatch endLatch = new CountDownLatch(1);
+ final PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiInt("position", data);
+ final ValueAnimator anim = ValueAnimator.ofPropertyValuesHolder(pvh);
+ anim.setInterpolator(null);
+ anim.setDuration(60);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+
+ anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float fraction = animation.getAnimatedFraction();
+ int[] values = (int[]) animation.getAnimatedValue();
+ assertEquals(3, values.length);
+
+ int expectedX = Math.round(fraction * (data.length - 1));
+ int expectedY = Math.round(fraction * (data.length - 1) * 2);
+
+ // Allow a delta of 1 for rounding errors.
+ assertEquals(expectedX, values[0], 1);
+ assertEquals(expectedY, values[1], 1);
+ assertEquals(0, values[2]);
+ }
+ });
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim.start();
+ }
+ });
+ assertTrue(endLatch.await(200, TimeUnit.MILLISECONDS));
+ }
+
+ public void testOfObject_Converter() throws Throwable {
+ // Test for PropertyValuesHolder.ofObject(String, TypeConverter<T, V>, Path)
+ // and for PropertyValuesHolder.ofObject(Property, TypeConverter<T, V>, Path)
+ // Create a path that contains two disconnected line segments. Check that the animated
+ // property x and property y always stay on the line segments.
+ Path path = new Path();
+ path.moveTo(LINE1_START, -LINE1_START);
+ path.lineTo(LINE1_END, -LINE1_END);
+ path.moveTo(LINE2_START, LINE2_START);
+ path.lineTo(LINE2_END, LINE2_END);
+ TypeConverter<PointF, Float> converter = new TypeConverter<PointF, Float>(
+ PointF.class, Float.class) {
+ @Override
+ public Float convert(PointF value) {
+ return (float) Math.sqrt(value.x * value.x + value.y * value.y);
+ }
+ };
+ final CountDownLatch endLatch = new CountDownLatch(3);
+
+ // Create three animators. The first one use a converter that converts the point to distance
+ // to origin. The second one does not have a type converter. The third animator uses a
+ // converter to changes sign of the x, y value of the input pointF.
+ FloatProperty property = new FloatProperty("distance") {
+ @Override
+ public void setValue(Object object, float value) {
+ }
+
+ @Override
+ public Object get(Object object) {
+ return null;
+ }
+ };
+ final PropertyValuesHolder pvh1 =
+ PropertyValuesHolder.ofObject(property, converter, path);
+ final ValueAnimator anim1 = ValueAnimator.ofPropertyValuesHolder(pvh1);
+ anim1.setDuration(100);
+ anim1.setInterpolator(null);
+ anim1.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+
+ final PropertyValuesHolder pvh2 =
+ PropertyValuesHolder.ofObject("position", null, path);
+ final ValueAnimator anim2 = ValueAnimator.ofPropertyValuesHolder(pvh2);
+ anim2.setDuration(100);
+ anim2.setInterpolator(null);
+ anim2.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+
+ TypeConverter<PointF, PointF> converter3 = new TypeConverter<PointF, PointF>(
+ PointF.class, PointF.class) {
+ PointF mValue = new PointF();
+ @Override
+ public PointF convert(PointF value) {
+ mValue.x = -value.x;
+ mValue.y = -value.y;
+ return mValue;
+ }
+ };
+ final PropertyValuesHolder pvh3 =
+ PropertyValuesHolder.ofObject("position", converter3, path);
+ final ValueAnimator anim3 = ValueAnimator.ofPropertyValuesHolder(pvh3);
+ anim3.setDuration(100);
+ anim3.setInterpolator(null);
+ anim3.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+
+ anim3.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ // Set the initial value of the distance to the distance between the first point on
+ // the path to the origin.
+ float mLastDistance = (float) (32 * Math.sqrt(2));
+ float mLastFraction = 0f;
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float fraction = anim1.getAnimatedFraction();
+ assertEquals(fraction, anim2.getAnimatedFraction());
+ assertEquals(fraction, anim3.getAnimatedFraction());
+ float distance = (Float) anim1.getAnimatedValue();
+ PointF position = (PointF) anim2.getAnimatedValue();
+ PointF positionReverseSign = (PointF) anim3.getAnimatedValue();
+ assertEquals(position.x, -positionReverseSign.x);
+ assertEquals(position.y, -positionReverseSign.y);
+
+ // Manually calculate the distance for the animator that doesn't have a
+ // TypeConverter, and expect the result to be the same as the animation value from
+ // the type converter.
+ float distanceFromPosition = (float) Math.sqrt(
+ position.x * position.x + position.y * position.y);
+ assertEquals(distance, distanceFromPosition, 0.0001f);
+
+ if (mLastFraction > 0.75) {
+ // In the 2nd line segment of the path, distance to origin should be increasing.
+ assertTrue(distance >= mLastDistance);
+ } else if (fraction < 0.75) {
+ assertTrue(distance <= mLastDistance);
+ }
+ mLastDistance = distance;
+ mLastFraction = fraction;
+ }
+ });
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim1.start();
+ anim2.start();
+ anim3.start();
+ }
+ });
+
+ // Wait until both of the animations finish
+ assertTrue(endLatch.await(200, TimeUnit.MILLISECONDS));
+ }
+
+ public void testSetConverter() throws Throwable {
+ // Test for PropertyValuesHolder.setConverter()
+ PropertyValuesHolder pvh = PropertyValuesHolder.ofObject("", null, 0f, 1f);
+ // Reverse the sign of the float in the converter, and use that value as the new type
+ // PointF's x value.
+ pvh.setConverter(new TypeConverter<Float, PointF>(Float.class, PointF.class) {
+ PointF mValue = new PointF();
+ @Override
+ public PointF convert(Float value) {
+ mValue.x = value * (-1f);
+ mValue.y = 0f;
+ return mValue;
+ }
+ });
+ final CountDownLatch endLatch = new CountDownLatch(2);
+
+ final ValueAnimator anim1 = ValueAnimator.ofPropertyValuesHolder(pvh);
+ anim1.setInterpolator(null);
+ anim1.setDuration(100);
+ anim1.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+
+ final ValueAnimator anim2 = ValueAnimator.ofFloat(0f, 1f);
+ anim2.setInterpolator(null);
+ anim2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ assertEquals(anim1.getAnimatedFraction(), anim2.getAnimatedFraction());
+ // Check that the pvh with type converter did reverse the sign of float, and set
+ // the x value of the PointF with it.
+ PointF value1 = (PointF) anim1.getAnimatedValue();
+ float value2 = (Float) anim2.getAnimatedValue();
+ assertEquals(value2, -value1.x);
+ assertEquals(0f, value1.y);
+ }
+ });
+ anim2.setDuration(100);
+ anim2.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endLatch.countDown();
+ }
+ });
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ anim1.start();
+ anim2.start();
+ }
+ });
+
+ // Wait until both of the animations finish
+ assertTrue(endLatch.await(200, TimeUnit.MILLISECONDS));
}
public void testSetProperty() throws Throwable {
diff --git a/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java b/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
index b778530..b43cc3a 100644
--- a/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
+++ b/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
@@ -19,6 +19,7 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
+import android.graphics.Color;
import android.test.ActivityInstrumentationTestCase2;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.LinearInterpolator;
@@ -393,6 +394,57 @@
assertTrue(animatedValue <= end);
}
+ public void testOfArgb() throws Throwable {
+ int start = 0xffff0000;
+ int end = 0xff0000ff;
+ int[] values = {start, end};
+ int startRed = Color.red(start);
+ int startBlue = Color.blue(start);
+ int endRed = Color.red(end);
+ int endBlue = Color.blue(end);
+ final ValueAnimator valueAnimatorLocal = ValueAnimator.ofArgb(values);
+ valueAnimatorLocal.setDuration(mDuration);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ valueAnimatorLocal.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ if (animation.getAnimatedFraction() > .05f) {
+ latch.countDown();
+ }
+ }
+ });
+
+ this.runTestOnUiThread(new Runnable(){
+ public void run() {
+ valueAnimatorLocal.start();
+ }
+ });
+ boolean isRunning = valueAnimatorLocal.isRunning();
+ assertTrue(isRunning);
+
+ assertTrue(latch.await(500, TimeUnit.MILLISECONDS));
+
+ Integer animatedValue = (Integer) valueAnimatorLocal.getAnimatedValue();
+ int alpha = Color.alpha(animatedValue);
+ int red = Color.red(animatedValue);
+ int green = Color.green(animatedValue);
+ int blue = Color.blue(animatedValue);
+ assertTrue(red < startRed);
+ assertTrue(red > endRed);
+ assertTrue(blue > startBlue);
+ assertTrue(blue < endBlue);
+ assertEquals(255, alpha);
+ assertEquals(0, green);
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ valueAnimatorLocal.cancel();
+ }
+ });
+ }
+
public void testNoDelayOnSeekAnimation() throws Throwable {
ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.setInterpolator(new LinearInterpolator());
@@ -418,6 +470,31 @@
});
}
+ public void testNotifiesAfterEnd() throws Throwable {
+ final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ assertTrue(animation.isStarted());
+ assertTrue(animation.isRunning());
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ assertFalse(animation.isRunning());
+ assertFalse(animation.isStarted());
+ super.onAnimationEnd(animation);
+ }
+ });
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ animator.start();
+ animator.end();
+ }
+ });
+ }
+
private ValueAnimator getAnimator() {
Object object = mActivity.view.newBall;
String property = "y";
diff --git a/tests/tests/app.usage/Android.mk b/tests/tests/app.usage/Android.mk
index 4cc3606..0303dbd 100644
--- a/tests/tests/app.usage/Android.mk
+++ b/tests/tests/app.usage/Android.mk
@@ -26,7 +26,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
index bd96d76..2c3c2ad 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
@@ -26,6 +26,9 @@
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkRequest;
+import android.net.TrafficStats;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
@@ -53,6 +56,12 @@
private static final long MINUTE = 1000 * 60;
private static final int TIMEOUT_MILLIS = 15000;
+ private static final String CHECK_CONNECTIVITY_URL = "http://www.265.com/";
+ private static final String CHECK_CALLBACK_URL = CHECK_CONNECTIVITY_URL;
+
+ private static final int NETWORK_TAG = 0xf00d;
+ private static final long THRESHOLD_BYTES = 2 * 1024 * 1024; // 2 MB
+
private interface NetworkInterfaceToTest {
int getNetworkType();
int getTransportType();
@@ -119,7 +128,7 @@
private String mWriteSettingsMode;
private String mUsageStatsMode;
- private void exerciseRemoteHost(Network network) throws Exception {
+ private void exerciseRemoteHost(Network network, URL url) throws Exception {
NetworkInfo networkInfo = mCm.getNetworkInfo(network);
if (networkInfo == null) {
Log.w(LOG_TAG, "Network info is null");
@@ -131,8 +140,8 @@
String originalKeepAlive = System.getProperty("http.keepAlive");
System.setProperty("http.keepAlive", "false");
try {
- urlc = (HttpURLConnection) network.openConnection(new URL(
- "http://www.265.com/"));
+ TrafficStats.setThreadStatsTag(NETWORK_TAG);
+ urlc = (HttpURLConnection) network.openConnection(url);
urlc.setConnectTimeout(TIMEOUT_MILLIS);
urlc.setUseCaches(false);
urlc.connect();
@@ -147,6 +156,7 @@
} catch (Exception e) {
Log.i(LOG_TAG, "Badness during exercising remote server: " + e);
} finally {
+ TrafficStats.clearThreadStatsTag();
if (in != null) {
try {
in.close();
@@ -229,10 +239,12 @@
private class NetworkCallback extends ConnectivityManager.NetworkCallback {
private long mTolerance;
+ private URL mUrl;
public boolean success;
- NetworkCallback(long tolerance) {
+ NetworkCallback(long tolerance, URL url) {
mTolerance = tolerance;
+ mUrl = url;
success = false;
}
@@ -240,7 +252,7 @@
public void onAvailable(Network network) {
try {
mStartTime = System.currentTimeMillis() - mTolerance;
- exerciseRemoteHost(network);
+ exerciseRemoteHost(network, mUrl);
mEndTime = System.currentTimeMillis() + mTolerance;
success = true;
synchronized(NetworkUsageStatsTest.this) {
@@ -260,7 +272,7 @@
if (!hasFeature) {
return false;
}
- NetworkCallback callback = new NetworkCallback(tolerance);
+ NetworkCallback callback = new NetworkCallback(tolerance, new URL(CHECK_CONNECTIVITY_URL));
mCm.requestNetwork(new NetworkRequest.Builder()
.addTransportType(sNetworkInterfacesToTest[networkTypeIndex].getTransportType())
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
@@ -520,10 +532,99 @@
}
}
+ public void testTagDetails() throws Exception {
+ for (int i = 0; i < sNetworkInterfacesToTest.length; ++i) {
+ // Relatively large tolerance to accommodate for history bucket size.
+ if (!shouldTestThisNetworkType(i, MINUTE * 120)) {
+ continue;
+ }
+ setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "allow");
+ NetworkStats result = null;
+ try {
+ result = mNsm.queryDetailsForUidTag(
+ sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
+ mStartTime, mEndTime, Process.myUid(), NETWORK_TAG);
+ assertTrue(result != null);
+ NetworkStats.Bucket bucket = new NetworkStats.Bucket();
+ long totalTxPackets = 0;
+ long totalRxPackets = 0;
+ long totalTxBytes = 0;
+ long totalRxBytes = 0;
+ while (result.hasNextBucket()) {
+ assertTrue(result.getNextBucket(bucket));
+ assertTimestamps(bucket);
+ assertEquals(bucket.getState(), NetworkStats.Bucket.STATE_ALL);
+ assertEquals(bucket.getUid(), Process.myUid());
+ if (bucket.getTag() == NETWORK_TAG) {
+ totalTxPackets += bucket.getTxPackets();
+ totalRxPackets += bucket.getRxPackets();
+ totalTxBytes += bucket.getTxBytes();
+ totalRxBytes += bucket.getRxBytes();
+ }
+ }
+ assertTrue("No Rx bytes tagged with 0x" + Integer.toHexString(NETWORK_TAG)
+ + " for uid " + Process.myUid(), totalRxBytes > 0);
+ assertTrue("No Rx packets tagged with " + Integer.toHexString(NETWORK_TAG)
+ + " for uid " + Process.myUid(), totalRxPackets > 0);
+ assertTrue("No Tx bytes tagged with 0x" + Integer.toHexString(NETWORK_TAG)
+ + " for uid " + Process.myUid(), totalTxBytes > 0);
+ assertTrue("No Tx packets tagged with 0x" + Integer.toHexString(NETWORK_TAG)
+ + " for uid " + Process.myUid(), totalTxPackets > 0);
+ } catch (SecurityException e) {
+ fail("testUidDetails fails with exception: " + e.toString());
+ } finally {
+ if (result != null) {
+ result.close();
+ }
+ }
+ setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "deny");
+ try {
+ result = mNsm.queryDetailsForUidTag(
+ sNetworkInterfacesToTest[i].getNetworkType(), getSubscriberId(i),
+ mStartTime, mEndTime, Process.myUid(), NETWORK_TAG);
+ fail("negative testUidDetails fails: no exception thrown.");
+ } catch (SecurityException e) {
+ // expected outcome
+ }
+ }
+ }
+
+ public void testCallback() throws Exception {
+ for (int i = 0; i < sNetworkInterfacesToTest.length; ++i) {
+ // Relatively large tolerance to accommodate for history bucket size.
+ if (!shouldTestThisNetworkType(i, MINUTE/2)) {
+ continue;
+ }
+ setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "allow");
+
+ TestUsageCallback usageCallback = new TestUsageCallback();
+ HandlerThread thread = new HandlerThread("callback-thread");
+ thread.start();
+ Handler handler = new Handler(thread.getLooper());
+ mNsm.registerUsageCallback(sNetworkInterfacesToTest[i].getNetworkType(),
+ getSubscriberId(i), THRESHOLD_BYTES, usageCallback, handler);
+
+ // TODO: Force traffic and check whether the callback is invoked.
+ // Right now the test only covers whether the callback can be registered, but not
+ // whether it is invoked upon data usage since we don't have a scalable way of
+ // storing files of >2MB in CTS.
+
+ mNsm.unregisterUsageCallback(usageCallback);
+ }
+ }
+
private void assertTimestamps(final NetworkStats.Bucket bucket) {
assertTrue("Start timestamp " + bucket.getStartTimeStamp() + " is less than " +
mStartTime, bucket.getStartTimeStamp() >= mStartTime);
assertTrue("End timestamp " + bucket.getEndTimeStamp() + " is greater than " +
mEndTime, bucket.getEndTimeStamp() <= mEndTime);
}
+
+ private static class TestUsageCallback extends NetworkStatsManager.UsageCallback {
+ @Override
+ public void onThresholdReached(int networkType, String subscriberId) {
+ Log.v(LOG_TAG, "Called onThresholdReached for networkType=" + networkType
+ + " subscriberId=" + subscriberId);
+ }
+ }
}
diff --git a/tests/tests/app/Android.mk b/tests/tests/app/Android.mk
index 08201a6..cf76aa0b 100644
--- a/tests/tests/app/Android.mk
+++ b/tests/tests/app/Android.mk
@@ -26,7 +26,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
index be6a759..e192a0c 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
@@ -107,4 +107,27 @@
}
}
+ public void testGetIccAuthentication() {
+ // EAP-SIM rand is 16 bytes.
+ String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM=";
+ String base64Challenge2 = "EMNxjsFrPCpm+KcgCmQGnwQ=";
+ if (!hasCellular) return;
+ try {
+ assertNull("getIccAuthentication should return null for empty data.",
+ mTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM,
+ TelephonyManager.AUTHTYPE_EAP_AKA, ""));
+ String response = mTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM,
+ TelephonyManager.AUTHTYPE_EAP_SIM, base64Challenge);
+ assertTrue("Response to EAP-SIM Challenge must not be Null.", response != null);
+ // response is base64 encoded. After decoding, the value should be:
+ // 1 length byte + SRES(4 bytes) + 1 length byte + Kc(8 bytes)
+ byte[] result = android.util.Base64.decode(response, android.util.Base64.DEFAULT);
+ assertTrue("Result length must be 14 bytes.", 14 == result.length);
+ String response2 = mTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM,
+ TelephonyManager.AUTHTYPE_EAP_SIM, base64Challenge2);
+ assertTrue("Two responses must be different.", !response.equals(response2));
+ } catch (SecurityException e) {
+ failMessage();
+ }
+ }
}
diff --git a/tests/tests/content/Android.mk b/tests/tests/content/Android.mk
index a22d539..73191c3 100644
--- a/tests/tests/content/Android.mk
+++ b/tests/tests/content/Android.mk
@@ -26,9 +26,16 @@
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 ctsdeviceutil ctstestrunner services.core
# Resource unit tests use a private locale and some densities
-LOCAL_AAPT_FLAGS = -c xx_YY -c cs -c small -c normal -c large -c xlarge \
+LOCAL_AAPT_FLAGS = -c small -c normal -c large -c xlarge \
-c 320dpi -c 240dpi -c 160dpi -c 32dpi \
- -c kok,kok_IN,kok_419,kok_419_VARIANT,kok_Knda_419,kok_Knda_419_VARIANT,kok_VARIANT,kok_Knda,tgl,tgl_PH
+ -c cs \
+ -c fil,fil_SA \
+ -c iw,iw_IL \
+ -c kok,kok_IN,kok_419,kok_419_VARIANT,kok_Knda_419,kok_Knda_419_VARIANT,kok_VARIANT,kok_Knda \
+ -c mk,mk_MK \
+ -c tgl,tgl_PH \
+ -c tlh \
+ -c xx_YY
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/content/res/values-b+fil+SA/configVarying.xml b/tests/tests/content/res/values-b+fil+SA/configVarying.xml
new file mode 100644
index 0000000..ba3c653
--- /dev/null
+++ b/tests/tests/content/res/values-b+fil+SA/configVarying.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<resources>
+ <bag type="configVarying" name="bag">
+ <item name="testString">bag fil SA</item>
+ </bag>
+</resources>
diff --git a/tests/tests/content/res/values-b+fil/configVarying.xml b/tests/tests/content/res/values-b+fil/configVarying.xml
new file mode 100644
index 0000000..2fa8f9f
--- /dev/null
+++ b/tests/tests/content/res/values-b+fil/configVarying.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<resources>
+ <item type="configVarying" name="simple">simple fil</item>
+</resources>
diff --git a/tests/tests/content/res/values-b+tlh/configVarying.xml b/tests/tests/content/res/values-b+tlh/configVarying.xml
new file mode 100644
index 0000000..48730f3
--- /dev/null
+++ b/tests/tests/content/res/values-b+tlh/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<resources>
+ <item type="configVarying" name="simple">simple tlh</item>
+ <bag type="configVarying" name="bag">
+ <item name="testString">bag tlh</item>
+ </bag>
+</resources>
diff --git a/tests/tests/content/res/values-iw-rIL/configVarying.xml b/tests/tests/content/res/values-iw-rIL/configVarying.xml
new file mode 100644
index 0000000..a42f026
--- /dev/null
+++ b/tests/tests/content/res/values-iw-rIL/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<resources>
+ <item type="configVarying" name="simple">simple iw IL</item>
+ <bag type="configVarying" name="bag">
+ <item name="testString">bag iw IL</item>
+ </bag>
+</resources>
diff --git a/tests/tests/content/res/values-iw/configVarying.xml b/tests/tests/content/res/values-iw/configVarying.xml
new file mode 100644
index 0000000..8eabd93
--- /dev/null
+++ b/tests/tests/content/res/values-iw/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<resources>
+ <item type="configVarying" name="simple">simple iw</item>
+ <bag type="configVarying" name="bag">
+ <item name="testString">bag iw</item>
+ </bag>
+</resources>
diff --git a/tests/tests/content/res/values-mk-rMK/configVarying.xml b/tests/tests/content/res/values-mk-rMK/configVarying.xml
new file mode 100644
index 0000000..14265ef
--- /dev/null
+++ b/tests/tests/content/res/values-mk-rMK/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<resources>
+ <item type="configVarying" name="simple">simple mk MK</item>
+ <bag type="configVarying" name="bag">
+ <item name="testString">bag mk MK</item>
+ </bag>
+</resources>
diff --git a/tests/tests/content/res/values-mk/configVarying.xml b/tests/tests/content/res/values-mk/configVarying.xml
new file mode 100644
index 0000000..edd1099
--- /dev/null
+++ b/tests/tests/content/res/values-mk/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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.
+-->
+
+<resources>
+ <item type="configVarying" name="simple">simple mk</item>
+ <bag type="configVarying" name="bag">
+ <item name="testString">bag mk</item>
+ </bag>
+</resources>
diff --git a/tests/tests/content/res/values/resources_test.xml b/tests/tests/content/res/values/resources_test.xml
index 91c2c4a..78385186 100644
--- a/tests/tests/content/res/values/resources_test.xml
+++ b/tests/tests/content/res/values/resources_test.xml
@@ -22,6 +22,10 @@
will be displayed in the app launcher and elsewhere. -->
<dimen name="app_icon_size">48px</dimen>
<dimen name="toast_y_offset">64dip</dimen>
+ <dimen name="pos_dimen_149">1.49px</dimen>
+ <dimen name="pos_dimen_151">1.51px</dimen>
+ <dimen name="neg_dimen_149">-1.49px</dimen>
+ <dimen name="neg_dimen_151">-1.51px</dimen>
<plurals name="plurals_test">
<item quantity="one">A dog</item>
<item quantity="other">Some dogs</item>
diff --git a/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java b/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
index 4893ec1..1387be0 100644
--- a/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
+++ b/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
@@ -139,13 +139,16 @@
public void testGetNonSystemLocales() {
// This is the list of locales built into this test package. It is basically the locales
// specified in the Android.mk files (assuming they have corresponding resources), plus the
- // special case for Filipino.
+ // special cases for Filipino.
final String KNOWN_LOCALES[] = {
"cs",
"fil",
"fil-PH",
+ "fil-SA",
"fr",
"fr-FR",
+ "iw",
+ "iw-IL",
"kok",
"kok-419",
"kok-419-variant",
@@ -154,8 +157,11 @@
"kok-Knda-419",
"kok-Knda-419-variant",
"kok-variant",
+ "mk",
+ "mk-MK",
"tgl",
"tgl-PH",
+ "tlh",
"xx",
"xx-YY"
};
diff --git a/tests/tests/content/src/android/content/res/cts/ConfigTest.java b/tests/tests/content/src/android/content/res/cts/ConfigTest.java
index 2390146..912de38 100644
--- a/tests/tests/content/src/android/content/res/cts/ConfigTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ConfigTest.java
@@ -1153,6 +1153,42 @@
}
@MediumTest
+ public void testNormalLocales() {
+ Resources res;
+ TotalConfig config = makeClassicConfig();
+ // Hebrew
+ config.setProperty(Properties.LANGUAGE, "iw");
+ res = config.getResources();
+ checkValue(res, R.configVarying.simple, "simple iw");
+ checkValue(res, R.configVarying.bag,
+ R.styleable.TestConfig, new String[]{"bag iw"});
+
+ // Hebrew for Israel
+ config.setProperty(Properties.LANGUAGE, "iw");
+ config.setProperty(Properties.COUNTRY, "IL");
+ res = config.getResources();
+ checkValue(res, R.configVarying.simple, "simple iw IL");
+ checkValue(res, R.configVarying.bag,
+ R.styleable.TestConfig, new String[]{"bag iw IL"});
+
+ config = makeClassicConfig();
+ // Macedonian
+ config.setProperty(Properties.LANGUAGE, "mk");
+ res = config.getResources();
+ checkValue(res, R.configVarying.simple, "simple mk");
+ checkValue(res, R.configVarying.bag,
+ R.styleable.TestConfig, new String[]{"bag mk"});
+
+ // Macedonian for Macedonia
+ config.setProperty(Properties.LANGUAGE, "mk");
+ config.setProperty(Properties.COUNTRY, "MK");
+ res = config.getResources();
+ checkValue(res, R.configVarying.simple, "simple mk MK");
+ checkValue(res, R.configVarying.bag,
+ R.styleable.TestConfig, new String[]{"bag mk MK"});
+ }
+
+ @MediumTest
public void testExtendedLocales() {
TotalConfig config = makeClassicConfig();
// BCP 47 Locale kok
@@ -1225,9 +1261,9 @@
config.setProperty(Properties.LANGUAGE, "fil");
config.setProperty(Properties.COUNTRY, "US");
Resources res = config.getResources();
- checkValue(res, R.configVarying.simple, "simple tl");
+ checkValue(res, R.configVarying.simple, "simple fil"); // We have this resource in 'fil'
checkValue(res, R.configVarying.bag,
- R.styleable.TestConfig, new String[] { "bag tl" });
+ R.styleable.TestConfig, new String[] { "bag tl" }); // But this comes from 'tl'
// Ensure that "fil-PH" is mapped to "tl-PH" correctly.
config = makeClassicConfig();
@@ -1238,6 +1274,24 @@
checkValue(res, R.configVarying.bag,
R.styleable.TestConfig, new String[] { "bag tl PH" });
+ // Ensure that "fil-SA" works with no "tl" version.
+ config = makeClassicConfig();
+ config.setProperty(Properties.LANGUAGE, "fil");
+ config.setProperty(Properties.COUNTRY, "SA");
+ res = config.getResources();
+ checkValue(res, R.configVarying.simple, "simple fil"); // This comes from 'fil'
+ checkValue(res, R.configVarying.bag,
+ R.styleable.TestConfig, new String[] { "bag fil SA" }); // And this from 'fil-SA'
+
+ // Ensure that "tlh" is not mistakenly treated as a "tl" variant.
+ config = makeClassicConfig();
+ config.setProperty(Properties.LANGUAGE, "tlh");
+ config.setProperty(Properties.COUNTRY, "US");
+ res = config.getResources();
+ checkValue(res, R.configVarying.simple, "simple tlh");
+ checkValue(res, R.configVarying.bag,
+ R.styleable.TestConfig, new String[] { "bag tlh" });
+
config = makeClassicConfig();
config.setProperty(Properties.LANGUAGE, "tgl");
res = config.getResources();
@@ -1276,8 +1330,9 @@
}
assertEquals(0, tlLocales.size());
- assertEquals(2, filLocales.size());
+ assertEquals(3, filLocales.size());
assertTrue(filLocales.contains("fil"));
assertTrue(filLocales.contains("fil-PH"));
+ assertTrue(filLocales.contains("fil-SA"));
}
}
diff --git a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
index 0f40ebd..0c51099 100644
--- a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
@@ -288,6 +288,10 @@
// app_icon_size is 48px, as defined in cts/tests/res/values/resources_test.xml
final int size = mResources.getDimensionPixelSize(R.dimen.app_icon_size);
assertEquals(48, size);
+ assertEquals(1, mResources.getDimensionPixelSize(R.dimen.pos_dimen_149));
+ assertEquals(2, mResources.getDimensionPixelSize(R.dimen.pos_dimen_151));
+ assertEquals(-1, mResources.getDimensionPixelSize(R.dimen.neg_dimen_149));
+ assertEquals(-2, mResources.getDimensionPixelSize(R.dimen.neg_dimen_151));
}
public void testGetDrawable() {
diff --git a/tests/tests/graphics/Android.mk b/tests/tests/graphics/Android.mk
index 7e26e07..40beee6 100644
--- a/tests/tests/graphics/Android.mk
+++ b/tests/tests/graphics/Android.mk
@@ -22,7 +22,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ctsdeviceutil ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-annotations android-support-test mockito-target ctsdeviceutil ctstestrunner
LOCAL_JNI_SHARED_LIBRARIES := libctsgraphics_jni
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/graphics/res/drawable/avd_empty_animator.xml b/tests/tests/graphics/res/drawable/avd_empty_animator.xml
new file mode 100644
index 0000000..cf6dd9a
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/avd_empty_animator.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <aapt:attr name="android:drawable">
+ <vector
+ android:width="32dp"
+ android:viewportWidth="32"
+ android:height="32dp"
+ android:viewportHeight="32">
+ <group
+ android:name="btn_radio_to_off_mtrl_0"
+ android:translateX="16"
+ android:translateY="16">
+ <group
+ android:name="ring_outer">
+ <path
+ android:name="ring_outer_path"
+ android:fillColor="#FF000000"
+ android:pathData="M 0.0,-9.0 c 4.9705627482,0.0 9.0,4.0294372518 9.0,9.0 c 0.0,4.9705627482 -4.0294372518,9.0 -9.0,9.0 c -4.9705627482,0.0 -9.0,-4.0294372518 -9.0,-9.0 c 0.0,-4.9705627482 4.0294372518,-9.0 9.0,-9.0 Z"/>
+ </group>
+ </group>
+ </vector>
+ </aapt:attr>
+ <target android:name="ring_outer_path">
+ <aapt:attr name="android:animation">
+ <!-- Empty animator set -->
+ <set/>
+ </aapt:attr>
+ </target>
+</animated-vector>
diff --git a/tests/tests/graphics/res/raw/a4_portrait_rgbb.pdf b/tests/tests/graphics/res/raw/a4_portrait_rgbb.pdf
new file mode 100644
index 0000000..ed373b7
--- /dev/null
+++ b/tests/tests/graphics/res/raw/a4_portrait_rgbb.pdf
Binary files differ
diff --git a/tests/tests/graphics/res/raw/a5_portrait_rgbb.pdf b/tests/tests/graphics/res/raw/a5_portrait_rgbb.pdf
new file mode 100644
index 0000000..44e5a7a
--- /dev/null
+++ b/tests/tests/graphics/res/raw/a5_portrait_rgbb.pdf
Binary files differ
diff --git a/tests/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_default.pdf b/tests/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_default.pdf
new file mode 100644
index 0000000..1f4ec0b
--- /dev/null
+++ b/tests/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_default.pdf
Binary files differ
diff --git a/tests/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_none.pdf b/tests/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_none.pdf
new file mode 100644
index 0000000..4d7a0f4
--- /dev/null
+++ b/tests/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_none.pdf
Binary files differ
diff --git a/tests/tests/graphics/res/raw/two_pages.pdf b/tests/tests/graphics/res/raw/two_pages.pdf
new file mode 100644
index 0000000..ee73ae6
--- /dev/null
+++ b/tests/tests/graphics/res/raw/two_pages.pdf
Binary files differ
diff --git a/tests/tests/graphics/src/android/graphics/cts/CameraTest.java b/tests/tests/graphics/src/android/graphics/cts/CameraTest.java
index a28d6ff..4fbe88b 100644
--- a/tests/tests/graphics/src/android/graphics/cts/CameraTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/CameraTest.java
@@ -18,8 +18,10 @@
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Matrix;
+import android.support.test.filters.SmallTest;
import android.test.AndroidTestCase;
+@SmallTest
public class CameraTest extends AndroidTestCase {
private Camera mCamera;
@@ -127,6 +129,35 @@
assertEquals(1.0f, f[8]);
}
+ public void testRotate() {
+ Matrix m1 = new Matrix();
+ preCompare(m1);
+
+ mCamera.rotate(15.0f, 30.0f, 45.0f);
+ Matrix m2 = new Matrix();
+ mCamera.getMatrix(m2);
+ assertFalse(m1.equals(m2));
+
+ float[] f = new float[9];
+ m2.getValues(f);
+ assertEquals(0.6123724f, f[0]);
+ assertEquals(0.6123724f, f[1]);
+ assertEquals(0.0f, f[2]);
+ assertEquals(-0.5915063f, f[3]);
+ assertEquals(0.774519f, f[4]);
+ assertEquals(0.0f, f[5]);
+ assertEquals(0.0009106233f, f[6]);
+ assertEquals(0.00027516257f, f[7]);
+ assertEquals(1.0f, f[8]);
+ }
+
+ public void testLocationAccessors() {
+ mCamera.setLocation(10.0f, 20.0f, 30.0f);
+ assertEquals(10.0f, mCamera.getLocationX());
+ assertEquals(20.0f, mCamera.getLocationY());
+ assertEquals(30.0f, mCamera.getLocationZ());
+ }
+
public void testApplyToCanvas() {
Canvas c1 = new Canvas();
mCamera.applyToCanvas(c1);
diff --git a/tests/tests/graphics/src/android/graphics/cts/ColorTest.java b/tests/tests/graphics/src/android/graphics/cts/ColorTest.java
index 760e3f9..c180906 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ColorTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ColorTest.java
@@ -16,31 +16,43 @@
package android.graphics.cts;
import android.graphics.Color;
-import android.test.AndroidTestCase;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
-public class ColorTest extends AndroidTestCase {
+import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ColorTest {
+ @Test
public void testAlpha(){
assertEquals(0xff, Color.alpha(Color.RED));
assertEquals(0xff, Color.alpha(Color.YELLOW));
new Color();
}
+ @Test
public void testArgb(){
assertEquals(Color.RED, Color.argb(0xff, 0xff, 0x00, 0x00));
assertEquals(Color.YELLOW, Color.argb(0xff, 0xff, 0xff, 0x00));
}
+ @Test
public void testBlue(){
assertEquals(0x00, Color.blue(Color.RED));
assertEquals(0x00, Color.blue(Color.YELLOW));
}
+ @Test
public void testGreen(){
assertEquals(0x00, Color.green(Color.RED));
assertEquals(0xff, Color.green(Color.GREEN));
}
+ @Test
public void testHSVToColor1(){
//abnormal case: hsv length less than 3
try{
@@ -56,6 +68,7 @@
assertEquals(Color.RED, Color.HSVToColor(hsv));
}
+ @Test
public void testHSVToColor2(){
//abnormal case: hsv length less than 3
try{
@@ -71,6 +84,7 @@
assertEquals(Color.RED, Color.HSVToColor(0xff, hsv));
}
+ @Test
public void testParseColor(){
//abnormal case: colorString starts with '#' but length is neither 7 nor 9
try{
@@ -104,16 +118,19 @@
assertEquals(Color.MAGENTA, Color.parseColor("magenta"));
}
+ @Test
public void testRed(){
assertEquals(0xff, Color.red(Color.RED));
assertEquals(0xff, Color.red(Color.YELLOW));
}
+ @Test
public void testRgb(){
assertEquals(Color.RED, Color.rgb(0xff, 0x00, 0x00));
assertEquals(Color.YELLOW, Color.rgb(0xff, 0xff, 0x00));
}
+ @Test
public void testRGBToHSV(){
//abnormal case: hsv length less than 3
try{
@@ -128,4 +145,14 @@
Color.RGBToHSV(0xff, 0x00, 0x00, hsv);
assertEquals(Color.RED, Color.HSVToColor(hsv));
}
+
+ @Test
+ public void testLuminance() {
+ assertEquals(0, Color.luminance(Color.BLACK), 0);
+ float eps = 0.000001f;
+ assertEquals(0.0722, Color.luminance(Color.BLUE), eps);
+ assertEquals(0.2126, Color.luminance(Color.RED), eps);
+ assertEquals(0.7152, Color.luminance(Color.GREEN), eps);
+ assertEquals(1, Color.luminance(Color.WHITE), 0);
+ }
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/MatrixTest.java b/tests/tests/graphics/src/android/graphics/cts/MatrixTest.java
index 29e4f5f..5b600f6 100644
--- a/tests/tests/graphics/src/android/graphics/cts/MatrixTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/MatrixTest.java
@@ -15,39 +15,68 @@
*/
package android.graphics.cts;
+import android.graphics.Camera;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.Matrix.ScaleToFit;
-import android.test.AndroidTestCase;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-public class MatrixTest extends AndroidTestCase {
+import static org.junit.Assert.*;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class MatrixTest {
private Matrix mMatrix;
private float[] mValues;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() {
mMatrix = new Matrix();
mValues = new float[9];
}
- public void testConstractor() {
- new Matrix();
- new Matrix(mMatrix);
+ @Test
+ public void testConstructor() {
+ assertTrue(new Matrix().isIdentity());
+ assertTrue(new Matrix(mMatrix).isIdentity());
}
+ @Test
public void testIsIdentity() {
assertTrue(mMatrix.isIdentity());
mMatrix.setScale(0f, 0f);
assertFalse(mMatrix.isIdentity());
}
+ @Test
public void testRectStaysRect() {
assertTrue(mMatrix.rectStaysRect());
mMatrix.postRotate(80);
assertFalse(mMatrix.rectStaysRect());
}
+ @Test
+ public void testIsAffine() {
+ assertTrue(mMatrix.isAffine());
+
+ // translate/scale/rotateZ don't affect whether matrix is affine
+ mMatrix.postTranslate(50, 50);
+ mMatrix.postScale(20, 4);
+ mMatrix.postRotate(80);
+ assertTrue(mMatrix.isAffine());
+
+ Camera camera = new Camera();
+ camera.setLocation(0, 0, 100);
+ camera.rotateX(20);
+ camera.getMatrix(mMatrix);
+ assertFalse(mMatrix.isAffine());
+ }
+
+ @Test
public void testSet() {
mValues[0] = 1000;
mMatrix.getValues(mValues);
@@ -56,9 +85,10 @@
mValues = new float[9];
mValues[0] = 2000;
matrix.getValues(mValues);
- assertEquals(1f, mValues[0]);
+ assertEquals(1f, mValues[0], 0f);
}
+ @Test
public void testEquals() {
mMatrix.setScale(1f, 2f);
Matrix matrix = new Matrix();
@@ -68,6 +98,7 @@
assertTrue(mMatrix.equals(matrix));
}
+ @Test
public void testReset() {
mMatrix.setScale(1f, 2f, 3f, 4f);
String expect = "[1.0, 0.0, 0.0][0.0, 2.0, -4.0][0.0, 0.0, 1.0]";
@@ -77,6 +108,7 @@
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testSetScale() {
String expect = "[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
@@ -85,6 +117,7 @@
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testSetScale2() {
String expect = "[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
@@ -94,6 +127,7 @@
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testSetRotate() {
mMatrix.setRotate(1f);
String expect = "[0.9998477, -0.017452406, 0.0]"
@@ -101,6 +135,7 @@
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testSetRotate2() {
mMatrix.setRotate(1f, 2f, 3f);
String expect = "[0.9998477, -0.017452406, 0.0526618]"
@@ -108,30 +143,35 @@
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testSetSinCos() {
mMatrix.setSinCos(1f, 2f);
String expect = "[2.0, -1.0, 0.0][1.0, 2.0, 0.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testSetSinCos2() {
mMatrix.setSinCos(1f, 2f, 3f, 4f);
String expect = "[2.0, -1.0, 1.0][1.0, 2.0, -7.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testSetSkew() {
mMatrix.setSkew(1f, 2f);
String expect = "[1.0, 1.0, 0.0][2.0, 1.0, 0.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testSetSkew2() {
mMatrix.setSkew(1f, 2f, 3f, 4f);
String expect = "[1.0, 1.0, -4.0][2.0, 1.0, -6.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testSetConcat() {
Matrix a = new Matrix();
Matrix b = new Matrix();
@@ -151,24 +191,28 @@
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testPreTranslate() {
assertTrue(mMatrix.preTranslate(1f, 2f));
String expect = "[1.0, 0.0, 1.0][0.0, 1.0, 2.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testPreScale() {
assertTrue(mMatrix.preScale(1f, 2f));
String expect = "[1.0, 0.0, 0.0][0.0, 2.0, 0.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testPreScale2() {
assertTrue(mMatrix.preScale(1f, 2f, 3f, 4f));
String expect = "[1.0, 0.0, 0.0][0.0, 2.0, -4.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testPreRotate() {
assertTrue(mMatrix.preRotate(1f));
String expect = "[0.9998477, -0.017452406, 0.0][0.017452406, 0.9998477, "
@@ -176,6 +220,7 @@
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testPreRotate2() {
assertTrue(mMatrix.preRotate(1f, 2f, 3f));
float[] values = new float[9];
@@ -185,18 +230,21 @@
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testPreSkew() {
assertTrue(mMatrix.preSkew(1f, 2f));
String expect = "[1.0, 1.0, 0.0][2.0, 1.0, 0.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testPreSkew2() {
assertTrue(mMatrix.preSkew(1f, 2f, 3f, 4f));
String expect = "[1.0, 1.0, -4.0][2.0, 1.0, -6.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testPreConcat() {
float[] values = new float[9];
values[0] = 1000;
@@ -207,24 +255,28 @@
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testPostTranslate() {
assertTrue(mMatrix.postTranslate(1f, 2f));
String expect = "[1.0, 0.0, 1.0][0.0, 1.0, 2.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testPostScale() {
assertTrue(mMatrix.postScale(1f, 2f));
String expect = "[1.0, 0.0, 0.0][0.0, 2.0, 0.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testPostScale2() {
assertTrue(mMatrix.postScale(1f, 2f, 3f, 4f));
String expect = "[1.0, 0.0, 0.0][0.0, 2.0, -4.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testPostRotate() {
assertTrue(mMatrix.postRotate(1f));
String expect = "[0.9998477, -0.017452406, 0.0]" +
@@ -232,6 +284,7 @@
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testPostRotate2() {
assertTrue(mMatrix.postRotate(1f, 2f, 3f));
String expect = "[0.9998477, -0.017452406, 0.0526618]" +
@@ -239,18 +292,21 @@
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testPostSkew() {
assertTrue(mMatrix.postSkew(1f, 2f));
String expect = "[1.0, 1.0, 0.0][2.0, 1.0, 0.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testPostSkew2() {
assertTrue(mMatrix.postSkew(1f, 2f, 3f, 4f));
String expect = "[1.0, 1.0, -4.0][2.0, 1.0, -6.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testPostConcat() {
Matrix matrix = new Matrix();
float[] values = new float[9];
@@ -262,6 +318,7 @@
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testSetRectToRect() {
RectF r1 = new RectF();
r1.set(1f, 2f, 3f, 3f);
@@ -292,10 +349,11 @@
try {
mMatrix.setRectToRect(null, null, ScaleToFit.CENTER);
fail("should throw exception");
- } catch (Exception e) {
+ } catch (Exception ignored) {
}
}
+ @Test
public void testInvert() {
Matrix matrix = new Matrix();
float[] values = new float[9];
@@ -310,11 +368,12 @@
try {
result = mMatrix.invert(null);
fail("should throw exception");
- } catch (Exception e) {
+ } catch (Exception ignored) {
}
assertFalse(result);
}
+ @Test
public void testSetPolyToPoly() {
float[] src = new float[9];
src[0] = 100f;
@@ -327,138 +386,147 @@
try {
mMatrix.setPolyToPoly(src, 0, dst, 0, 5);
fail("should throw exception");
- } catch (Exception e) {
+ } catch (Exception ignored) {
}
}
+ @Test
public void testMapPoints() {
float[] value = new float[9];
value[0] = 100f;
mMatrix.mapPoints(value);
- assertEquals(value[0], 100f);
+ assertEquals(value[0], 100f, 0f);
try {
mMatrix.mapPoints(null);
fail("should throw exception");
- } catch (Exception e) {
+ } catch (Exception ignored) {
}
}
+ @Test
public void testMapPoints2() {
float[] dst = new float[9];
dst[0] = 100f;
float[] src = new float[9];
src[0] = 200f;
mMatrix.mapPoints(dst, src);
- assertEquals(dst[0], 200f);
+ assertEquals(dst[0], 200f, 0f);
try {
mMatrix.mapPoints(new float[8], new float[9]);
fail("should throw exception");
- } catch (Exception e) {
+ } catch (Exception ignored) {
}
}
+ @Test
public void testMapPoints3() {
float[] dst = new float[9];
dst[0] = 100f;
float[] src = new float[9];
src[0] = 200f;
mMatrix.mapPoints(dst, 0, src, 0, 9 >> 1);
- assertEquals(dst[0], 200f);
+ assertEquals(dst[0], 200f, 0f);
try {
mMatrix.mapPoints(null, 0, new float[9], 0, 1);
fail("should throw exception");
- } catch (Exception e) {
+ } catch (Exception ignored) {
}
}
+ @Test
public void testMapVectors() {
float[] values = new float[9];
- values = new float[9];
values[0] = 100f;
mMatrix.mapVectors(values);
- assertEquals(values[0], 100f);
+ assertEquals(values[0], 100f, 0f);
try {
mMatrix.mapVectors(null);
fail("should throw exception");
- } catch (Exception e) {
+ } catch (Exception ignored) {
}
}
+ @Test
public void testMapVectors2() {
float[] src = new float[9];
src[0] = 100f;
float[] dst = new float[9];
dst[0] = 200f;
mMatrix.mapVectors(dst, src);
- assertEquals(dst[0], 100f);
+ assertEquals(dst[0], 100f, 0f);
try {
mMatrix.mapVectors(new float[9], new float[8]);
fail("should throw exception");
- } catch (Exception e) {
+ } catch (Exception ignored) {
}
}
+ @Test
public void testMapVectors3() {
float[] src = new float[9];
src[0] = 100f;
float[] dst = new float[9];
dst[0] = 200f;
mMatrix.mapVectors(dst, 0, src, 0, 1);
- assertEquals(dst[0], 100f);
+ assertEquals(dst[0], 100f, 0f);
try {
mMatrix.mapVectors(dst, 0, src, 0, 10);
fail("should throw exception");
- } catch (Exception e) {
+ } catch (Exception ignored) {
}
}
+ @Test
public void testMapRadius() {
- assertEquals(mMatrix.mapRadius(100f), 100f);
+ assertEquals(mMatrix.mapRadius(100f), 100f, 0f);
assertEquals(mMatrix.mapRadius(Float.MAX_VALUE),
- Float.POSITIVE_INFINITY);
- assertEquals(mMatrix.mapRadius(Float.MIN_VALUE), 0f);
+ Float.POSITIVE_INFINITY, 0f);
+ assertEquals(mMatrix.mapRadius(Float.MIN_VALUE), 0f, 0f);
}
+ @Test
public void testMapRect() {
RectF r = new RectF();
r.set(1f, 2f, 3f, 4f);
assertTrue(mMatrix.mapRect(r));
- assertEquals(1f, r.left);
- assertEquals(2f, r.top);
- assertEquals(3f, r.right);
- assertEquals(4f, r.bottom);
+ assertEquals(1f, r.left, 0f);
+ assertEquals(2f, r.top, 0f);
+ assertEquals(3f, r.right, 0f);
+ assertEquals(4f, r.bottom, 0f);
try {
mMatrix.mapRect(null);
fail("should throw exception");
- } catch (Exception e) {
+ } catch (Exception ignored) {
}
}
+ @Test
public void testMapRect2() {
RectF dst = new RectF();
dst.set(100f, 100f, 200f, 200f);
RectF src = new RectF();
dst.set(10f, 10f, 20f, 20f);
assertTrue(mMatrix.mapRect(dst, src));
- assertEquals(0f, dst.left);
- assertEquals(0f, dst.top);
- assertEquals(0f, dst.right);
- assertEquals(0f, dst.bottom);
+ assertEquals(0f, dst.left, 0f);
+ assertEquals(0f, dst.top, 0f);
+ assertEquals(0f, dst.right, 0f);
+ assertEquals(0f, dst.bottom, 0f);
- assertEquals(0f, src.left);
- assertEquals(0f, src.top);
- assertEquals(0f, src.right);
- assertEquals(0f, src.bottom);
+ assertEquals(0f, src.left, 0f);
+ assertEquals(0f, src.top, 0f);
+ assertEquals(0f, src.right, 0f);
+ assertEquals(0f, src.bottom, 0f);
try {
mMatrix.mapRect(null, null);
fail("should throw exception");
- } catch (Exception e) {
+ } catch (Exception ignored) {
}
}
+ @Test
public void testAccessValues() {
Matrix matrix = new Matrix();
mMatrix.invert(matrix);
@@ -478,15 +546,18 @@
+ values[6] + ", " + values[7] + ", " + values[8] + "]";
}
+ @Test
public void testToString() {
assertNotNull(mMatrix.toString());
}
+ @Test
public void testToShortString() {
String expect = "[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]";
assertEquals(expect, mMatrix.toShortString());
}
+ @Test
public void testSetTranslate() {
mMatrix.setTranslate(2f, 3f);
String expect = "[1.0, 0.0, 2.0][0.0, 1.0, 3.0][0.0, 0.0, 1.0]";
diff --git a/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java b/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
index 8b73380..8dcd32d 100644
--- a/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
@@ -16,9 +16,6 @@
package android.graphics.cts;
-import android.graphics.cts.R;
-
-
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -29,8 +26,10 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
+import android.support.test.filters.SmallTest;
import android.test.AndroidTestCase;
+@SmallTest
public class NinePatchTest extends AndroidTestCase {
private static int ALPHA_OPAQUE = 0xFF;
@@ -57,13 +56,37 @@
}
public void testConstructor() {
- mNinePatch = null;
+ try {
+ mNinePatch = new NinePatch(mBitmap, new byte[2]);
+ fail("should throw exception");
+ } catch (Exception e) {
+ }
+
try {
mNinePatch = new NinePatch(mBitmap, new byte[2], NAME);
fail("should throw exception");
} catch (Exception e) {
}
+
+ mNinePatch = new NinePatch(mBitmap, mChunk);
+ assertEquals(mBitmap, mNinePatch.getBitmap());
+ assertEquals(null, mNinePatch.getName());
+
mNinePatch = new NinePatch(mBitmap, mChunk, NAME);
+ assertEquals(mBitmap, mNinePatch.getBitmap());
+ assertEquals(NAME, mNinePatch.getName());
+ }
+
+ public void testPaintAccessors() {
+ Paint p = new Paint();
+ mNinePatch = new NinePatch(mBitmap, mChunk, NAME);
+ assertNull(mNinePatch.getPaint());
+
+ mNinePatch.setPaint(p);
+ assertEquals(p, mNinePatch.getPaint());
+
+ mNinePatch.setPaint(null);
+ assertNull(mNinePatch.getPaint());
}
public void testIsNinePatchChunk() {
@@ -71,7 +94,6 @@
Bitmap bitmap = Bitmap.createBitmap(COLOR, 10, 10, Bitmap.Config.ARGB_4444);
assertFalse(NinePatch.isNinePatchChunk(bitmap.getNinePatchChunk()));
assertFalse(NinePatch.isNinePatchChunk(null));
-
}
public void testDraw() {
diff --git a/tests/tests/graphics/src/android/graphics/cts/OutlineTest.java b/tests/tests/graphics/src/android/graphics/cts/OutlineTest.java
index 4b01916..57a20ee 100644
--- a/tests/tests/graphics/src/android/graphics/cts/OutlineTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/OutlineTest.java
@@ -19,14 +19,15 @@
import android.graphics.Outline;
import android.graphics.Path;
import android.graphics.Rect;
+import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
import org.junit.Test;
+import org.junit.runner.RunWith;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
@SmallTest
+@RunWith(AndroidJUnit4.class)
public class OutlineTest {
@Test
public void testDefaults() {
@@ -40,6 +41,20 @@
}
@Test
+ public void testCopyConstructor() {
+ Outline orig = new Outline();
+ orig.setAlpha(0.5f);
+ orig.setRect(10, 10, 20, 20);
+
+ Outline copy = new Outline(orig);
+ assertEquals(0.5f, copy.getAlpha(), 0.0f);
+
+ Rect copyRect = new Rect();
+ copy.getRect(copyRect);
+ assertEquals(new Rect(10, 10, 20, 20), copyRect);
+ }
+
+ @Test
public void testGetSetAlpha() {
Outline outline = new Outline();
@@ -60,6 +75,21 @@
}
@Test
+ public void testSet() {
+ Outline orig = new Outline();
+ orig.setAlpha(0.5f);
+ orig.setRect(10, 10, 20, 20);
+
+ Outline copy = new Outline();
+ copy.set(orig);
+ assertEquals(0.5f, copy.getAlpha(), 0.0f);
+
+ Rect copyRect = new Rect();
+ copy.getRect(copyRect);
+ assertEquals(new Rect(10, 10, 20, 20), copyRect);
+ }
+
+ @Test
public void testSetRect() {
Outline outline = new Outline();
Rect outRect = new Rect();
@@ -135,6 +165,11 @@
assertTrue(outline.getRect(outRect)); // is round rect, so works
assertTrue(outline.canClip()); // is round rect, so works
assertFalse(outline.isEmpty());
+
+ outline.setOval(new Rect(0, 0, 50, 50)); // same x & y radii, so round rect
+ assertTrue(outline.getRect(outRect)); // is round rect, so works
+ assertTrue(outline.canClip()); // is round rect, so works
+ assertFalse(outline.isEmpty());
}
@Test
diff --git a/tests/tests/graphics/src/android/graphics/cts/PathTest.java b/tests/tests/graphics/src/android/graphics/cts/PathTest.java
index 6e93400..6aef2cf 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PathTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PathTest.java
@@ -16,8 +16,6 @@
package android.graphics.cts;
-import junit.framework.TestCase;
-
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -25,8 +23,16 @@
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-public class PathTest extends TestCase {
+import static org.junit.Assert.*;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PathTest {
// Test constants
private static final float LEFT = 10.0f;
@@ -36,6 +42,7 @@
private static final float XCOORD = 40.0f;
private static final float YCOORD = 40.0f;
+ @Test
public void testConstructor() {
// new the Path instance
new Path();
@@ -44,9 +51,8 @@
new Path(new Path());
}
+ @Test
public void testAddRect1() {
-
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM);
@@ -54,34 +60,34 @@
assertFalse(path.isEmpty());
}
+ @Test
public void testAddRect2() {
-
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
path.addRect(LEFT, TOP, RIGHT, BOTTOM, Path.Direction.CW);
assertFalse(path.isEmpty());
}
+ @Test
public void testMoveTo() {
- // new the Path instance
Path path = new Path();
path.moveTo(10.0f, 10.0f);
}
+ @Test
public void testSet() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
Path path1 = new Path();
- setPath(path1);
+ addRectToPath(path1);
path.set(path1);
assertPathsAreEquivalent(path, path1);
}
+ @Test
public void testSetCleanOld() {
Path path = new Path();
- setPath(path);
+ addRectToPath(path);
path.addRect(new RectF(0, 0, 10, 10), Path.Direction.CW);
Path path1 = new Path();
path1.addRect(new RectF(10, 10, 20, 20), Path.Direction.CW);
@@ -89,15 +95,16 @@
assertPathsAreEquivalent(path, path1);
}
+ @Test
public void testSetEmptyPath() {
- // new the Path instance
Path path = new Path();
- setPath(path);
+ addRectToPath(path);
Path path1 = new Path();
path.set(path1);
assertPathsAreEquivalent(path, path1);
}
+ @Test
public void testAccessFillType() {
// set the expected value
Path.FillType expected1 = Path.FillType.EVEN_ODD;
@@ -118,52 +125,49 @@
assertEquals(expected4, path.getFillType());
}
+ @Test
public void testRQuadTo() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
path.rQuadTo(5.0f, 5.0f, 10.0f, 10.0f);
assertFalse(path.isEmpty());
}
+ @Test
public void testTransform1() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
Path dst = new Path();
- setPath(path);
+ addRectToPath(path);
path.transform(new Matrix(), dst);
assertFalse(dst.isEmpty());
}
- public void testTransform2() {
-
- }
-
+ @Test
public void testLineTo() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
path.lineTo(XCOORD, YCOORD);
assertFalse(path.isEmpty());
}
+ @Test
public void testClose() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
- setPath(path);
+ addRectToPath(path);
path.close();
}
+ @Test
public void testQuadTo() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
path.quadTo(20.0f, 20.0f, 40.0f, 40.0f);
assertFalse(path.isEmpty());
}
+ @Test
public void testAddCircle() {
// new the Path instance
Path path = new Path();
@@ -172,8 +176,8 @@
assertFalse(path.isEmpty());
}
+ @Test
public void testArcTo1() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM);
@@ -181,8 +185,8 @@
assertFalse(path.isEmpty());
}
+ @Test
public void testArcTo2() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM);
@@ -190,81 +194,77 @@
assertFalse(path.isEmpty());
}
+ @Test
public void testComputeBounds1() {
-
RectF expected = new RectF(0.0f, 0.0f, 0.0f, 0.0f);
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
RectF bounds = new RectF();
path.computeBounds(bounds, true);
- assertEquals(expected.width(), bounds.width());
- assertEquals(expected.height(), bounds.height());
+ assertEquals(expected.width(), bounds.width(), 0.0f);
+ assertEquals(expected.height(), bounds.height(), 0.0f);
path.computeBounds(bounds, false);
- assertEquals(expected.width(), bounds.width());
- assertEquals(expected.height(), bounds.height());
+ assertEquals(expected.width(), bounds.width(), 0.0f);
+ assertEquals(expected.height(), bounds.height(), 0.0f);
}
+ @Test
public void testComputeBounds2() {
-
RectF expected = new RectF(LEFT, TOP, RIGHT, BOTTOM);
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
RectF bounds = new RectF(LEFT, TOP, RIGHT, BOTTOM);
path.addRect(bounds, Path.Direction.CW);
path.computeBounds(bounds, true);
- assertEquals(expected.width(), bounds.width());
- assertEquals(expected.height(), bounds.height());
+ assertEquals(expected.width(), bounds.width(), 0.0f);
+ assertEquals(expected.height(), bounds.height(), 0.0f);
path.computeBounds(bounds, false);
- assertEquals(expected.width(), bounds.width());
- assertEquals(expected.height(), bounds.height());
+ assertEquals(expected.width(), bounds.width(), 0.0f);
+ assertEquals(expected.height(), bounds.height(), 0.0f);
}
+ @Test
public void testRMoveTo() {
- // new the Path instance
}
+ @Test
public void testSetLastPoint() {
- // new the Path instance
Path path = new Path();
path.setLastPoint(10.0f, 10.0f);
}
+ @Test
public void testRLineTo() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
path.rLineTo(10.0f, 10.0f);
assertFalse(path.isEmpty());
}
+ @Test
public void testIsEmpty() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
- setPath(path);
+ addRectToPath(path);
assertFalse(path.isEmpty());
}
+ @Test
public void testRewind() {
-
- // set the expected value
Path.FillType expected = Path.FillType.EVEN_ODD;
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
- setPath(path);
+ addRectToPath(path);
path.rewind();
path.setFillType(Path.FillType.EVEN_ODD);
assertTrue(path.isEmpty());
assertEquals(expected, path.getFillType());
}
+ @Test
public void testAddOval() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM);
@@ -272,50 +272,46 @@
assertFalse(path.isEmpty());
}
+ @Test
public void testIsRect() {
-
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
- setPath(path);
+ addRectToPath(path);
}
- public void testIncReserve() {
- }
-
+ @Test
public void testAddPath1() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
Path src = new Path();
- setPath(src);
+ addRectToPath(src);
path.addPath(src, 10.0f, 10.0f);
assertFalse(path.isEmpty());
}
+ @Test
public void testAddPath2() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
Path src = new Path();
- setPath(src);
+ addRectToPath(src);
path.addPath(src);
assertFalse(path.isEmpty());
}
+ @Test
public void testAddPath3() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
Path src = new Path();
- setPath(src);
+ addRectToPath(src);
Matrix matrix = new Matrix();
path.addPath(src, matrix);
assertFalse(path.isEmpty());
}
+ @Test
public void testAddRoundRect1() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM);
@@ -323,8 +319,8 @@
assertFalse(path.isEmpty());
}
+ @Test
public void testAddRoundRect2() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM);
@@ -336,59 +332,84 @@
assertFalse(path.isEmpty());
}
- public void testIsInverseFillType() {
+ @Test
+ public void testIsConvex1() {
+ Path path = new Path();
+ path.addRect(0, 0, 100, 10, Path.Direction.CW);
+ assertTrue(path.isConvex());
- // new the Path instance
+ path.addRect(0, 0, 10, 100, Path.Direction.CW);
+ assertFalse(path.isConvex()); // path is concave
+ }
+
+ @Test
+ public void testIsConvex2() {
+ Path path = new Path();
+ path.addRect(0, 0, 40, 40, Path.Direction.CW);
+ assertTrue(path.isConvex());
+
+ path.addRect(10, 10, 30, 30, Path.Direction.CCW);
+ assertFalse(path.isConvex()); // path has hole, isn't convex
+ }
+
+ @Test
+ public void testIsConvex3() {
+ Path path = new Path();
+ path.addRect(0, 0, 10, 10, Path.Direction.CW);
+ assertTrue(path.isConvex());
+
+ path.addRect(0, 20, 10, 10, Path.Direction.CW);
+ assertFalse(path.isConvex()); // path isn't one convex shape
+ }
+
+ @Test
+ public void testIsInverseFillType() {
Path path = new Path();
assertFalse(path.isInverseFillType());
path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
assertTrue(path.isInverseFillType());
}
+ @Test
public void testOffset1() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
- setPath(path);
+ addRectToPath(path);
Path dst = new Path();
path.offset(XCOORD, YCOORD, dst);
assertFalse(dst.isEmpty());
}
- public void testOffset2() {
- // new the Path instance
- }
-
+ @Test
public void testCubicTo() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
path.cubicTo(10.0f, 10.0f, 20.0f, 20.0f, 30.0f, 30.0f);
assertFalse(path.isEmpty());
}
+ @Test
public void testReset() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
Path path1 = new Path();
- setPath(path1);
+ addRectToPath(path1);
path.set(path1);
assertFalse(path.isEmpty());
path.reset();
assertTrue(path.isEmpty());
}
+ @Test
public void testToggleInverseFillType() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
path.toggleInverseFillType();
assertTrue(path.isInverseFillType());
}
+ @Test
public void testAddArc() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
RectF oval = new RectF(LEFT, TOP, RIGHT, BOTTOM);
@@ -396,8 +417,8 @@
assertFalse(path.isEmpty());
}
+ @Test
public void testRCubicTo() {
- // new the Path instance
Path path = new Path();
assertTrue(path.isEmpty());
path.rCubicTo(10.0f, 10.0f, 11.0f, 11.0f, 12.0f, 12.0f);
@@ -423,7 +444,7 @@
return bitmap;
}
- private void setPath(Path path) {
+ private void addRectToPath(Path path) {
RectF rect = new RectF(LEFT, TOP, RIGHT, BOTTOM);
path.addRect(rect, Path.Direction.CW);
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/PointFTest.java b/tests/tests/graphics/src/android/graphics/cts/PointFTest.java
index 77b72d4..0bef3e7 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PointFTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PointFTest.java
@@ -18,33 +18,21 @@
import android.graphics.Point;
import android.graphics.PointF;
+import android.os.Parcel;
+import android.support.test.filters.SmallTest;
import android.test.AndroidTestCase;
+@SmallTest
public class PointFTest extends AndroidTestCase {
private PointF mPointF;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mPointF = null;
- }
-
public void testConstructor() {
-
- mPointF = null;
- // new the PointF instance
mPointF = new PointF();
-
- mPointF = null;
- // new the PointF instance
mPointF = new PointF(10.0f, 10.0f);
- mPointF = null;
Point point = new Point(10, 10);
- // new the PointF instance
mPointF = new PointF(point);
-
}
public void testNegate() {
@@ -91,4 +79,20 @@
assertEquals(11.1f, mPointF.y);
}
+ public void testDescribeContents() {
+ mPointF = new PointF(10.0f, 20.0f);
+ assertEquals(0, mPointF.describeContents());
+ }
+
+ public void testParceling() {
+ mPointF = new PointF(10.0f, 20.0f);
+ Parcel p = Parcel.obtain();
+ mPointF.writeToParcel(p, 0);
+ p.setDataPosition(0);
+
+ mPointF = new PointF();
+ mPointF.readFromParcel(p);
+ assertEquals(10.0f, mPointF.x);
+ assertEquals(20.0f, mPointF.y);
+ }
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/PointTest.java b/tests/tests/graphics/src/android/graphics/cts/PointTest.java
index e4ede58..bee4034 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PointTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PointTest.java
@@ -17,30 +17,21 @@
package android.graphics.cts;
import android.graphics.Point;
+import android.os.Parcel;
+import android.support.test.filters.SmallTest;
import android.test.AndroidTestCase;
+@SmallTest
public class PointTest extends AndroidTestCase {
private Point mPoint;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mPoint = null;
- }
-
public void testConstructor() {
-
- // new the Point instance
mPoint = new Point();
-
- // new the Point instance
mPoint = new Point(10, 10);
Point point = new Point(10, 10);
- // new the Point instance
mPoint = new Point(point);
-
}
public void testSet() {
@@ -89,4 +80,20 @@
assertEquals(-10, mPoint.y);
}
+ public void testDescribeContents() {
+ mPoint = new Point(10, 20);
+ assertEquals(0, mPoint.describeContents());
+ }
+
+ public void testParceling() {
+ mPoint = new Point(10, 20);
+ Parcel p = Parcel.obtain();
+ mPoint.writeToParcel(p, 0);
+ p.setDataPosition(0);
+
+ mPoint = new Point();
+ mPoint.readFromParcel(p);
+ assertEquals(10, mPoint.x);
+ assertEquals(20, mPoint.y);
+ }
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/RectFTest.java b/tests/tests/graphics/src/android/graphics/cts/RectFTest.java
index f5788af..0240690 100644
--- a/tests/tests/graphics/src/android/graphics/cts/RectFTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/RectFTest.java
@@ -16,46 +16,28 @@
package android.graphics.cts;
-
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Parcel;
+import android.support.test.filters.SmallTest;
import android.test.AndroidTestCase;
+@SmallTest
public class RectFTest extends AndroidTestCase {
-
private RectF mRectF;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mRectF = null;
- }
-
public void testConstructor() {
-
- mRectF = null;
- // new the RectF instance
mRectF = new RectF();
-
- mRectF = null;
- // new the RectF instance
mRectF = new RectF(1.5f, 2.5f, 20.3f, 40.9f);
- mRectF = null;
RectF rectF = new RectF(1.5f, 2.5f, 20.3f, 40.9f);
- // new the RectF instance
mRectF = new RectF(rectF);
- mRectF = null;
Rect rect = new Rect(0, 0, 10, 10);
- // new the RectF instance
mRectF = new RectF(rect);
-
}
public void testSort() {
-
mRectF = new RectF(10, 10, 5, 5);
assertEquals(10.0f, mRectF.left);
assertEquals(10.0f, mRectF.top);
@@ -67,22 +49,18 @@
assertEquals(5.0f, mRectF.top);
assertEquals(10.0f, mRectF.right);
assertEquals(10.0f, mRectF.bottom);
-
}
public void testSet1() {
-
mRectF = new RectF();
mRectF.set(1.0f, 2.0f, 3.0f, 4.0f);
assertEquals(1.0f, mRectF.left);
assertEquals(2.0f, mRectF.top);
assertEquals(3.0f, mRectF.right);
assertEquals(4.0f, mRectF.bottom);
-
}
public void testSet2() {
-
RectF rectF = new RectF(1.0f, 2.0f, 3.0f, 4.0f);
mRectF = new RectF();
mRectF.set(rectF);
@@ -90,11 +68,9 @@
assertEquals(2.0f, mRectF.top);
assertEquals(3.0f, mRectF.right);
assertEquals(4.0f, mRectF.bottom);
-
}
public void testSet3() {
-
Rect rect = new Rect(1, 2, 3, 4);
mRectF = new RectF();
mRectF.set(rect);
@@ -102,11 +78,9 @@
assertEquals(2.0f, mRectF.top);
assertEquals(3.0f, mRectF.right);
assertEquals(4.0f, mRectF.bottom);
-
}
public void testIntersects1() {
-
mRectF = new RectF(0, 0, 10, 10);
assertTrue(mRectF.intersects(5, 5, 15, 15));
assertEquals(0.0f, mRectF.left);
@@ -120,11 +94,9 @@
assertEquals(0.0f, mRectF.top);
assertEquals(10.0f, mRectF.right);
assertEquals(10.0f, mRectF.bottom);
-
}
public void testIntersects2() {
-
RectF rectF1;
RectF rectF2;
@@ -135,11 +107,9 @@
rectF1 = new RectF(0, 0, 10, 10);
rectF2 = new RectF(15, 15, 25, 25);
assertFalse(RectF.intersects(rectF1, rectF2));
-
}
public void testIntersect1() {
-
mRectF = new RectF(0, 0, 10, 10);
assertTrue(mRectF.intersect(5, 5, 15, 15));
assertEquals(5.0f, mRectF.left);
@@ -153,11 +123,9 @@
assertEquals(0.0f, mRectF.top);
assertEquals(10.0f, mRectF.right);
assertEquals(10.0f, mRectF.bottom);
-
}
public void testIntersect2() {
-
RectF rectF;
mRectF = new RectF(0, 0, 10, 10);
@@ -175,11 +143,9 @@
assertEquals(0.0f, mRectF.top);
assertEquals(10.0f, mRectF.right);
assertEquals(10.0f, mRectF.bottom);
-
}
public void testUnion1() {
-
// Both rect1 and rect2 are not empty.
// 1. left < right, top < bottom
// this.left < this.right, this.top < this.bottom
@@ -225,11 +191,9 @@
assertEquals(0.0f, mRectF.left);
assertEquals(1.0f, mRectF.right);
assertEquals(1.0f, mRectF.bottom);
-
}
public void testUnion2() {
-
RectF rectF;
// Both rect1 and rect2 are not empty.
@@ -282,11 +246,9 @@
assertEquals(0.0f, mRectF.left);
assertEquals(1.0f, mRectF.right);
assertEquals(1.0f, mRectF.bottom);
-
}
public void testUnion3() {
-
// rect1 is not empty (x > right, y > bottom).
mRectF = new RectF(0.0f, 0.0f, 1.0f, 1.0f);
mRectF.union(2.0f, 2.0f);
@@ -318,21 +280,17 @@
assertEquals(0.0f, mRectF.left);
assertEquals(2.0f, mRectF.right);
assertEquals(2.0f, mRectF.bottom);
-
}
public void testContains1() {
-
mRectF = new RectF(1.0f, 1.0f, 20.0f, 20.0f);
assertFalse(mRectF.contains(0.9f, 0.9f));
assertTrue(mRectF.contains(1.0f, 1.0f));
assertTrue(mRectF.contains(19.9f, 19.9f));
assertFalse(mRectF.contains(20.0f, 20.0f));
-
}
public void testContains2() {
-
mRectF = new RectF(1.0f, 1.0f, 20.0f, 20.0f);
assertTrue(mRectF.contains(1.0f, 1.0f, 20.0f, 20.0f));
assertTrue(mRectF.contains(2.0f, 2.0f, 19.0f, 19.0f));
@@ -341,7 +299,6 @@
}
public void testContains3() {
-
RectF rectF;
mRectF = new RectF(1.0f, 1.0f, 20.0f, 20.0f);
rectF = new RectF(1.0f, 1.0f, 20.0f, 20.0f);
@@ -352,22 +309,18 @@
assertFalse(mRectF.contains(rectF));
rectF = new RectF(0.0f, 0.0f, 19.0f, 19.0f);
assertFalse(mRectF.contains(rectF));
-
}
public void testOffset() {
-
mRectF = new RectF(5, 5, 10, 10);
mRectF.offset(1.0f, 1.0f);
assertEquals(6.0f, mRectF.left);
assertEquals(6.0f, mRectF.top);
assertEquals(11.0f, mRectF.right);
assertEquals(11.0f, mRectF.bottom);
-
}
public void testInset() {
-
mRectF = new RectF(5.0f, 5.0f, 10.0f, 10.0f);
mRectF.inset(1.0f, 1.0f);
assertEquals(6.0f, mRectF.left);
@@ -381,7 +334,6 @@
assertEquals(4.0f, mRectF.top);
assertEquals(11.0f, mRectF.right);
assertEquals(11.0f, mRectF.bottom);
-
}
public void testHeight() {
@@ -395,18 +347,15 @@
}
public void testOffsetTo() {
-
mRectF = new RectF(5, 5, 10, 10);
mRectF.offsetTo(1.0f, 1.0f);
assertEquals(1.0f, mRectF.left);
assertEquals(1.0f, mRectF.top);
assertEquals(6.0f, mRectF.right);
assertEquals(6.0f, mRectF.bottom);
-
}
public void testSetEmpty() {
-
// Before setEmpty()
mRectF = new RectF(1, 2, 3, 4);
assertEquals(1.0f, mRectF.left);
@@ -420,11 +369,9 @@
assertEquals(0.0f, mRectF.top);
assertEquals(0.0f, mRectF.right);
assertEquals(0.0f, mRectF.bottom);
-
}
public void testIsEmpty() {
-
mRectF = new RectF();
assertTrue(mRectF.isEmpty());
mRectF = new RectF(1.0f, 1.0f, 1.0f, 1.0f);
@@ -433,22 +380,18 @@
assertTrue(mRectF.isEmpty());
mRectF = new RectF(1.0f, 1.0f, 20.0f, 20.0f);
assertFalse(mRectF.isEmpty());
-
}
public void testCenterX() {
-
mRectF = new RectF(10.0f, 10.0f, 20.0f, 20.0f);
assertEquals(15.0f, mRectF.centerX());
mRectF = new RectF(10.5f, 10.0f, 20.0f, 20.0f);
assertEquals(15.25f, mRectF.centerX());
mRectF = new RectF(10.4f, 10.0f, 20.0f, 20.0f);
assertEquals(15.2f, mRectF.centerX());
-
}
public void testCenterY() {
-
mRectF = new RectF(10.0f, 10.0f, 20.0f, 20.0f);
assertEquals(15.0f, mRectF.centerY());
mRectF = new RectF(10.0f, 10.5f, 20.0f, 20.0f);
@@ -458,12 +401,16 @@
}
public void testToString() {
- mRectF = new RectF();
- assertNotNull(mRectF.toString());
+ mRectF = new RectF(10.0f, 20.0f, 30.0f, 40.0f);
+ assertEquals("RectF(10.0, 20.0, 30.0, 40.0)", mRectF.toString());
+ }
+
+ public void testToShortString() {
+ mRectF = new RectF(10.0f, 20.0f, 30.0f, 40.0f);
+ assertEquals("[10.0,20.0][30.0,40.0]", mRectF.toShortString());
}
public void testSetIntersect() {
-
RectF rectF1 = new RectF(0, 0, 10, 10);
RectF rectF2 = new RectF(5, 5, 15, 15);
@@ -482,11 +429,9 @@
assertEquals(5.0f, mRectF.top);
assertEquals(10.0f, mRectF.right);
assertEquals(10.0f, mRectF.bottom);
-
}
public void testRoundOut() {
-
Rect rect = new Rect();
mRectF = new RectF(1.2f, 1.8f, 5.2f, 5.8f);
mRectF.roundOut(rect);
@@ -494,11 +439,9 @@
assertEquals(1, rect.top);
assertEquals(6, rect.right);
assertEquals(6, rect.bottom);
-
}
public void testRound() {
-
Rect rect = new Rect();
mRectF = new RectF(1.2f, 1.8f, 5.2f, 5.8f);
mRectF.round(rect);
@@ -506,7 +449,6 @@
assertEquals(2, rect.top);
assertEquals(5, rect.right);
assertEquals(6, rect.bottom);
-
}
public void testWriteReadParcel() {
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/Animatable2_AnimationCallbackTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/Animatable2_AnimationCallbackTest.java
new file mode 100644
index 0000000..deb0e87
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/Animatable2_AnimationCallbackTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.graphics.drawable.cts;
+
+import junit.framework.TestCase;
+
+import android.graphics.drawable.Animatable2.AnimationCallback;
+import android.support.test.filters.SmallTest;
+
+@SmallTest
+public class Animatable2_AnimationCallbackTest extends TestCase {
+
+ public void testCallback() {
+ // These are no-op methods. Just make sure they don't crash.
+ AnimationCallback callback = new AnimationCallback() {};
+ callback.onAnimationStart(null);
+ callback.onAnimationEnd(null);
+ }
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
index 5dabdfd..4e6c357 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
@@ -169,6 +169,28 @@
}
@SmallTest
+ public void testEmptyAnimatorSet() throws InterruptedException {
+ int resId = R.drawable.avd_empty_animator;
+ final MyCallback callback = new MyCallback();
+ final AnimatedVectorDrawable d1 =
+ (AnimatedVectorDrawable) mResources.getDrawable(resId);
+ d1.registerAnimationCallback(callback);
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mActivity.setContentView(mLayoutId);
+ ImageView imageView = (ImageView) mActivity.findViewById(mImageViewId);
+ imageView.setImageDrawable(d1);
+ d1.start();
+ }
+ });
+
+ getInstrumentation().waitForIdleSync();
+ // Check that the AVD with empty AnimatorSet has finished
+ assertTrue(callback.mEnd);
+ }
+
+ @SmallTest
public void testGetChangingConfigurations() {
AnimatedVectorDrawable avd = new AnimatedVectorDrawable();
ConstantState constantState = avd.getConstantState();
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerStateTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerStateTest.java
index 8cbecab..726466c 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerStateTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerStateTest.java
@@ -16,6 +16,7 @@
package android.graphics.drawable.cts;
+import junit.framework.TestCase;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
@@ -23,12 +24,12 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.DrawableContainer;
-import android.graphics.drawable.LevelListDrawable;
import android.graphics.drawable.DrawableContainer.DrawableContainerState;
+import android.graphics.drawable.LevelListDrawable;
+import android.support.test.filters.SmallTest;
-import junit.framework.TestCase;
-
-public class DrawableContainerStateTest extends TestCase{
+@SmallTest
+public class DrawableContainerStateTest extends TestCase {
private DrawableContainerState mDrawableContainerState;
private DrawableContainer mDrawableContainer;
@@ -36,6 +37,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
+
// DrawableContainerState has no public constructor. Obtain an instance through
// LevelListDrawable.getConstants(). This is fine for testing the final methods of
// DrawableContainerState.
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
index bc452f3..81d9386 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
@@ -16,14 +16,30 @@
package android.graphics.drawable.cts;
-import android.content.res.Resources.Theme;
-import android.graphics.drawable.Drawable.Callback;
-import android.view.View;
-import android.graphics.cts.R;
-
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.content.ContentResolver;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.cts.R;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Drawable.Callback;
+import android.net.Uri;
+import android.support.test.filters.SmallTest;
+import android.test.AndroidTestCase;
+import android.util.AttributeSet;
+import android.util.StateSet;
+import android.util.TypedValue;
+import android.util.Xml;
+import android.view.View;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -32,24 +48,11 @@
import java.io.InputStream;
import java.io.OutputStream;
-import android.content.ContentResolver;
-import android.content.res.Resources;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.test.AndroidTestCase;
-import android.util.AttributeSet;
-import android.util.StateSet;
-import android.util.TypedValue;
-import android.util.Xml;
-
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+@SmallTest
public class DrawableTest extends AndroidTestCase {
Resources mResources;
@@ -546,13 +549,22 @@
}
public void testScheduleSelf() {
- MockDrawable mockDrawable = new MockDrawable();
- MockCallback mockCallback = new MockCallback();
- mockDrawable.setCallback(mockCallback);
+ Drawable mockDrawable = new MockDrawable();
mockDrawable.scheduleSelf(null, 1000L);
- assertEquals(mockDrawable, mockCallback.getScheduleDrawable());
- assertNull(mockCallback.getRunnable());
- assertEquals(1000L, mockCallback.getWhen());
+
+ Runnable runnable = mock(Runnable.class);
+ mockDrawable.scheduleSelf(runnable, 1000L);
+
+ Callback mockCallback = mock(Callback.class);
+ mockDrawable.setCallback(mockCallback);
+ mockDrawable.scheduleSelf(runnable, 1000L);
+ verify(mockCallback).scheduleDrawable(eq(mockDrawable), eq(runnable), eq(1000L));
+
+ mockDrawable.scheduleSelf(runnable, 0L);
+ verify(mockCallback).scheduleDrawable(eq(mockDrawable), eq(runnable), eq(0L));
+
+ mockDrawable.scheduleSelf(runnable, -1000L);
+ verify(mockCallback).scheduleDrawable(eq(mockDrawable), eq(runnable), eq(-1000L));
}
public void testAccessCallback() {
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
index 713f61a..b062073 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
@@ -16,9 +16,13 @@
package android.graphics.drawable.cts;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.app.Activity;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
@@ -28,11 +32,14 @@
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.graphics.cts.MockActivity;
import android.graphics.cts.R;
import android.graphics.drawable.Drawable.ConstantState;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.GradientDrawable.Orientation;
-import android.test.AndroidTestCase;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.AttributeSet;
@@ -42,9 +49,21 @@
import java.util.Arrays;
import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
-public class GradientDrawableTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class GradientDrawableTest {
+
+ @Rule
+ public ActivityTestRule<MockActivity> mActivityRule
+ = new ActivityTestRule<>(MockActivity.class);
+
@SmallTest
+ @Test
public void testConstructor() {
int[] color = new int[] {1, 2, 3};
@@ -54,6 +73,7 @@
}
@SmallTest
+ @Test
public void testGetOpacity() {
GradientDrawable gradientDrawable = new GradientDrawable();
assertEquals("Default opacity is TRANSLUCENT",
@@ -87,6 +107,7 @@
}
@SmallTest
+ @Test
public void testSetOrientation() {
GradientDrawable gradientDrawable = new GradientDrawable();
Orientation orientation;
@@ -98,6 +119,7 @@
}
@SmallTest
+ @Test
public void testSetCornerRadii() {
float[] radii = new float[] {1.0f, 2.0f, 3.0f};
@@ -116,6 +138,7 @@
}
@SmallTest
+ @Test
public void testSetCornerRadius() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -124,6 +147,22 @@
}
@SmallTest
+ @Test
+ public void testGetCornerRadius() {
+ GradientDrawable gradientDrawable = new GradientDrawable();
+ gradientDrawable.setCornerRadius(5.5f);
+ assertEquals(gradientDrawable.getCornerRadius(), 5.5f, 0);
+ float[] radii = new float[] {1.0f, 2.0f, 3.0f};
+ gradientDrawable.setCornerRadii(radii);
+ assertEquals(5.5f, gradientDrawable.getCornerRadius(), 0);
+ gradientDrawable.setShape(GradientDrawable.OVAL);
+ assertEquals(5.5f, gradientDrawable.getCornerRadius(), 0);
+ gradientDrawable.setCornerRadii(null);
+ assertEquals(0, gradientDrawable.getCornerRadius(), 0);
+ }
+
+ @SmallTest
+ @Test
public void testSetStroke() {
helpTestSetStroke(2, Color.RED);
helpTestSetStroke(-2, Color.TRANSPARENT);
@@ -137,6 +176,7 @@
}
@SmallTest
+ @Test
public void testSetStroke_WidthGap() {
helpTestSetStroke_WidthGap(2, Color.RED, 3.4f, 5.5f);
helpTestSetStroke_WidthGap(-2, Color.TRANSPARENT, -3.4f, -5.5f);
@@ -151,6 +191,7 @@
}
@SmallTest
+ @Test
public void testSetStrokeList() {
helpTestSetStrokeList(2, ColorStateList.valueOf(Color.RED));
helpTestSetStrokeList(-2, ColorStateList.valueOf(Color.TRANSPARENT));
@@ -165,6 +206,7 @@
}
@SmallTest
+ @Test
public void testSetStrokeList_WidthGap() {
helpTestSetStrokeList_WidthGap(2, ColorStateList.valueOf(Color.RED), 3.4f, 5.5f);
helpTestSetStrokeList_WidthGap(-2, ColorStateList.valueOf(Color.TRANSPARENT), -3.4f, -5.5f);
@@ -179,6 +221,7 @@
}
@SmallTest
+ @Test
public void testSetSize() {
helpTestSetSize(6, 4);
helpTestSetSize(-30, -40);
@@ -194,6 +237,7 @@
}
@SmallTest
+ @Test
public void testSetShape() {
GradientDrawable gradientDrawable = new GradientDrawable();
int shape;
@@ -210,6 +254,7 @@
}
@SmallTest
+ @Test
public void testSetGradientType() {
GradientDrawable gradientDrawable = new GradientDrawable();
int gradientType;
@@ -226,6 +271,7 @@
}
@SmallTest
+ @Test
public void testSetGradientCenter() {
GradientDrawable gradientDrawable = new GradientDrawable();
float centerX;
@@ -245,11 +291,12 @@
centerX = 0.0f;
centerY = 0.0f;
gradientDrawable.setGradientCenter(centerX, centerY);
- assertEquals(centerX, gradientDrawable.getGradientCenterX());
- assertEquals(centerY, gradientDrawable.getGradientCenterY());
+ assertEquals(centerX, gradientDrawable.getGradientCenterX(), 0.01f);
+ assertEquals(centerY, gradientDrawable.getGradientCenterY(), 0.01f);
}
@SmallTest
+ @Test
public void testSetGradientRadius() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -258,6 +305,7 @@
}
@SmallTest
+ @Test
public void testSetUseLevel() {
GradientDrawable gradientDrawable = new GradientDrawable();
boolean useLevel;
@@ -276,6 +324,7 @@
}
@SmallTest
+ @Test
public void testDraw() {
GradientDrawable gradientDrawable = new GradientDrawable();
Canvas c = new Canvas();
@@ -286,6 +335,7 @@
}
@SmallTest
+ @Test
public void testSetColor() {
GradientDrawable gradientDrawable = new GradientDrawable();
int color;
@@ -302,6 +352,7 @@
}
@SmallTest
+ @Test
public void testSetColors() {
GradientDrawable gradientDrawable = new GradientDrawable();
int[] colors;
@@ -318,6 +369,7 @@
}
@SmallTest
+ @Test
public void testSetColorList() {
GradientDrawable gradientDrawable = new GradientDrawable();
ColorStateList color;
@@ -332,6 +384,7 @@
}
@SmallTest
+ @Test
public void testGetChangingConfigurations() {
GradientDrawable gradientDrawable = new GradientDrawable();
assertEquals(0, gradientDrawable.getChangingConfigurations());
@@ -344,6 +397,7 @@
}
@SmallTest
+ @Test
public void testSetAlpha() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -352,6 +406,7 @@
}
@SmallTest
+ @Test
public void testSetDither() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -360,6 +415,7 @@
}
@SmallTest
+ @Test
public void testSetColorFilter() {
GradientDrawable gradientDrawable = new GradientDrawable();
ColorFilter cf = new ColorFilter();
@@ -370,6 +426,7 @@
}
@SmallTest
+ @Test
public void testInflate() throws XmlPullParserException, IOException {
GradientDrawable gradientDrawable = new GradientDrawable();
Rect rect = new Rect();
@@ -379,7 +436,7 @@
assertEquals(0, rect.right);
assertEquals(0, rect.bottom);
- Resources resources = mContext.getResources();
+ Resources resources = mActivityRule.getActivity().getResources();
XmlPullParser parser = resources.getXml(R.drawable.gradientdrawable);
AttributeSet attrs = Xml.asAttributeSet(parser);
@@ -415,9 +472,10 @@
}
@SmallTest
+ @Test
public void testInflateGradientRadius() throws XmlPullParserException, IOException {
Rect parentBounds = new Rect(0, 0, 100, 100);
- Resources resources = mContext.getResources();
+ Resources resources = mActivityRule.getActivity().getResources();
GradientDrawable gradientDrawable;
float radius;
@@ -436,6 +494,7 @@
}
@SmallTest
+ @Test
public void testGetIntrinsicWidth() {
GradientDrawable gradientDrawable = new GradientDrawable();
gradientDrawable.setSize(6, 4);
@@ -446,6 +505,7 @@
}
@SmallTest
+ @Test
public void testGetIntrinsicHeight() {
GradientDrawable gradientDrawable = new GradientDrawable();
gradientDrawable.setSize(5, 3);
@@ -456,14 +516,16 @@
}
@SmallTest
+ @Test
public void testGetConstantState() {
GradientDrawable gradientDrawable = new GradientDrawable();
assertNotNull(gradientDrawable.getConstantState());
}
@SmallTest
+ @Test
public void testMutate() {
- Resources resources = mContext.getResources();
+ Resources resources = mActivityRule.getActivity().getResources();
GradientDrawable d1 = (GradientDrawable) resources.getDrawable(R.drawable.gradientdrawable);
GradientDrawable d2 = (GradientDrawable) resources.getDrawable(R.drawable.gradientdrawable);
GradientDrawable d3 = (GradientDrawable) resources.getDrawable(R.drawable.gradientdrawable);
@@ -495,8 +557,9 @@
}
@MediumTest
+ @Test
public void testPreloadDensity() throws XmlPullParserException, IOException {
- final Resources res = getContext().getResources();
+ final Resources res = mActivityRule.getActivity().getResources();
final int densityDpi = res.getConfiguration().densityDpi;
try {
testPreloadDensityInner(res, densityDpi);
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawable_ShaderFactoryTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawable_ShaderFactoryTest.java
index b736519..0447fb2 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawable_ShaderFactoryTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawable_ShaderFactoryTest.java
@@ -17,10 +17,26 @@
package android.graphics.drawable.cts;
import junit.framework.TestCase;
-import android.graphics.drawable.ShapeDrawable;
+import android.graphics.Shader;
+import android.graphics.drawable.ShapeDrawable.ShaderFactory;
+import android.support.test.filters.SmallTest;
+
+@SmallTest
public class ShapeDrawable_ShaderFactoryTest extends TestCase {
+
public void testResize() {
- // resize is an abstract function.
+ // This is an abstract function, but coverage
+ // complains if we don't call it.
+ ShaderFactory impl = new ShaderFactoryImpl();
+ assertNull(impl.resize(0, 0));
+ }
+
+ private class ShaderFactoryImpl extends ShaderFactory {
+
+ @Override
+ public Shader resize(int width, int height) {
+ return null;
+ }
}
}
diff --git a/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTest.java b/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTest.java
new file mode 100644
index 0000000..a1c32ab
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTest.java
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.graphics.pdf.cts;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.cts.R;
+import android.graphics.pdf.PdfRenderer;
+import android.graphics.pdf.PdfRenderer.Page;
+import android.os.ParcelFileDescriptor;
+import android.support.annotation.NonNull;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * All test for {@link PdfRenderer} beside the valid transformation parameter tests of {@link
+ * PdfRenderer.Page#render}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class PdfRendererTest {
+ private static final String LOG_TAG = "PdfRendererTest";
+
+ private static final int A5_PORTRAIT_PRINTSCALING_DEFAULT =
+ R.raw.a5_portrait_rgbb_1_6_printscaling_default;
+ private static final int A5_PORTRAIT_PRINTSCALING_NONE =
+ R.raw.a5_portrait_rgbb_1_6_printscaling_none;
+ private static final int TWO_PAGES = R.raw.two_pages;
+
+ private Context mContext;
+
+ /**
+ * Run a runnable and expect and exception of a certain type.
+ *
+ * @param r The {@link Invokable} to run
+ * @param expectedClass The expected exception type
+ */
+ private void assertException(@NonNull Invokable r,
+ @NonNull Class<? extends Exception> expectedClass) {
+ try {
+ r.run();
+ } catch (Exception e) {
+ if (e.getClass().isAssignableFrom(expectedClass)) {
+ return;
+ } else {
+ Log.e(LOG_TAG, "Incorrect exception", e);
+ throw new AssertionError("Expected: " + expectedClass.getName() + ", got: "
+ + e.getClass().getName());
+ }
+ }
+
+ throw new AssertionError("No exception thrown");
+ }
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ }
+
+ @Test
+ public void constructRendererNull() throws Exception {
+ assertException(() -> new PdfRenderer(null), NullPointerException.class);
+ }
+
+ @Test
+ @Ignore("Makes all subsequent tests fail")
+ public void constructRendererFromNonPDF() throws Exception {
+ // Open jpg as if it was a PDF
+ ParcelFileDescriptor fd = mContext.getResources().openRawResourceFd(R.raw.testimage)
+ .getParcelFileDescriptor();
+ assertException(() -> new PdfRenderer(fd), IOException.class);
+ }
+
+ @Test
+ public void useRendererAfterClose() throws Exception {
+ PdfRenderer renderer = Utils.createRenderer(Utils.A4_PORTRAIT, mContext);
+ renderer.close();
+
+ assertException(() -> renderer.close(), IllegalStateException.class);
+ assertException(() -> renderer.getPageCount(), IllegalStateException.class);
+ assertException(() -> renderer.shouldScaleForPrinting(), IllegalStateException.class);
+ assertException(() -> renderer.openPage(0), IllegalStateException.class);
+ }
+
+ @Test
+ public void usePageAfterClose() throws Exception {
+ PdfRenderer renderer = Utils.createRenderer(Utils.A4_PORTRAIT, mContext);
+ Page page = renderer.openPage(0);
+ page.close();
+
+ // Legacy behavior: The properties are cached, hence they are still available after the page
+ // is closed
+ page.getHeight();
+ page.getWidth();
+ page.getIndex();
+ assertException(() -> page.close(), IllegalStateException.class);
+
+ // Legacy support. An IllegalStateException would be nice by unfortunately the legacy
+ // implementation returned NullPointerException
+ assertException(() -> page.render(null, null, null, Page.RENDER_MODE_FOR_DISPLAY),
+ NullPointerException.class);
+
+ renderer.close();
+ }
+
+ @Test
+ public void closeWithOpenPage() throws Exception {
+ PdfRenderer renderer = Utils.createRenderer(Utils.A4_PORTRAIT, mContext);
+ Page page = renderer.openPage(0);
+
+ assertException(() -> renderer.close(), IllegalStateException.class);
+
+ page.close();
+ renderer.close();
+ }
+
+ @Test
+ public void openTwoPages() throws Exception {
+ try (PdfRenderer renderer = Utils.createRenderer(TWO_PAGES, mContext)) {
+ // Cannot open two pages at once
+ Page page = renderer.openPage(0);
+ assertException(() -> renderer.openPage(1), IllegalStateException.class);
+
+ page.close();
+ }
+ }
+
+ @Test
+ public void testPageCount() throws Exception {
+ try (PdfRenderer renderer = Utils.createRenderer(TWO_PAGES, mContext)) {
+ assertEquals(2, renderer.getPageCount());
+ }
+ }
+
+ @Test
+ public void testOpenPage() throws Exception {
+ try (PdfRenderer renderer = Utils.createRenderer(TWO_PAGES, mContext)) {
+ assertException(() -> renderer.openPage(-1), IllegalArgumentException.class);
+ Page page0 = renderer.openPage(0);
+ page0.close();
+ Page page1 = renderer.openPage(1);
+ page1.close();
+ assertException(() -> renderer.openPage(2), IllegalArgumentException.class);
+ }
+ }
+
+ @Test
+ public void testPageSize() throws Exception {
+ try (PdfRenderer renderer = Utils.createRenderer(Utils.A4_PORTRAIT, mContext)) {
+ try (Page page = renderer.openPage(0)) {
+ assertEquals(Utils.A4_HEIGHT_PTS, page.getHeight());
+ assertEquals(Utils.A4_WIDTH_PTS, page.getWidth());
+ }
+ }
+ }
+
+ @Test
+ public void testPrintScaleDefault() throws Exception {
+ try (PdfRenderer renderer = Utils.createRenderer(Utils.A5_PORTRAIT, mContext)) {
+ assertTrue(renderer.shouldScaleForPrinting());
+ }
+ }
+
+ @Test
+ public void testPrintScalePDF16Default() throws Exception {
+ try (PdfRenderer renderer = Utils
+ .createRenderer(A5_PORTRAIT_PRINTSCALING_DEFAULT, mContext)) {
+ assertTrue(renderer.shouldScaleForPrinting());
+ }
+ }
+
+ @Test
+ public void testPrintScalePDF16None() throws Exception {
+ try (PdfRenderer renderer = Utils.createRenderer(A5_PORTRAIT_PRINTSCALING_NONE, mContext)) {
+ assertFalse(renderer.shouldScaleForPrinting());
+ }
+ }
+
+ /**
+ * Take 16 color probes in the middle of the 16 segments of the page in the following pattern:
+ * <pre>
+ * +----+----+----+----+
+ * | 0 : 1 : 2 : 3 |
+ * +....:....:....:....+
+ * | 4 : 5 : 6 : 7 |
+ * +....:....:....:....+
+ * | 8 : 9 : 10 : 11 |
+ * +....:....:....:....+
+ * | 12 : 13 : 14 : 15 |
+ * +----+----+----+----+
+ * </pre>
+ *
+ * @param bm The bitmap to probe
+ *
+ * @return The color at the probes
+ */
+ private @NonNull int[] getColorProbes(@NonNull Bitmap bm) {
+ int[] probes = new int[16];
+
+ for (int row = 0; row < 4; row++) {
+ for (int column = 0; column < 4; column++) {
+ probes[row * 4 + column] = bm.getPixel((int) (bm.getWidth() * (column + 0.5) / 4),
+ (int) (bm.getHeight() * (row + 0.5) / 4));
+ }
+ }
+
+ return probes;
+ }
+
+ /**
+ * Implementation for {@link #renderNoTransformationAndComparePointsForScreen} and {@link
+ * #renderNoTransformationAndComparePointsForPrint}.
+ *
+ * @param renderMode The render mode to use
+ *
+ * @throws Exception If anything was unexpected
+ */
+ private void renderNoTransformationAndComparePoints(int renderMode) throws Exception {
+ Bitmap bm = Utils.renderWithTransform(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS,
+ Utils.A4_PORTRAIT, null, null, renderMode, mContext);
+ int[] probes = getColorProbes(bm);
+
+ // Compare rendering to expected result. This ensures that all other tests in this class do
+ // not accidentally all compare empty bitmaps.
+ assertEquals(Color.RED, probes[0]);
+ assertEquals(Color.RED, probes[1]);
+ assertEquals(Color.GREEN, probes[2]);
+ assertEquals(Color.GREEN, probes[3]);
+ assertEquals(Color.RED, probes[4]);
+ assertEquals(Color.RED, probes[5]);
+ assertEquals(Color.GREEN, probes[6]);
+ assertEquals(Color.GREEN, probes[7]);
+ assertEquals(Color.BLUE, probes[8]);
+ assertEquals(Color.BLUE, probes[9]);
+ assertEquals(Color.BLACK, probes[10]);
+ assertEquals(Color.BLACK, probes[11]);
+ assertEquals(Color.BLUE, probes[12]);
+ assertEquals(Color.BLUE, probes[13]);
+ assertEquals(Color.BLACK, probes[14]);
+ assertEquals(Color.BLACK, probes[15]);
+ }
+
+ @Test
+ public void renderNoTransformationAndComparePointsForScreen() throws Exception {
+ renderNoTransformationAndComparePoints(Page.RENDER_MODE_FOR_DISPLAY);
+ }
+
+ @Test
+ public void renderNoTransformationAndComparePointsForPrint() throws Exception {
+ renderNoTransformationAndComparePoints(Page.RENDER_MODE_FOR_PRINT);
+ }
+
+ @Test
+ public void renderPerspective() throws Exception {
+ Matrix transform = new Matrix();
+
+ transform.setValues(new float[] { 1, 1, 1, 1, 1, 1, 1, 1, 1 });
+
+ assertException(() -> Utils
+ .renderWithTransform(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS,
+ Utils.A4_PORTRAIT, null, transform, Page.RENDER_MODE_FOR_DISPLAY,
+ mContext), IllegalArgumentException.class);
+ }
+
+ @Test
+ public void render45degreeRotationTranslationAndScaleAndClip() throws Exception {
+ Matrix transform = new Matrix();
+ // Rotate on top left corner
+ transform.postRotate(45);
+ // Move
+ transform.postTranslate(Utils.A4_WIDTH_PTS / 4, Utils.A4_HEIGHT_PTS / 4);
+ // Scale to 75%
+ transform.postScale(0.75f, 0.75f);
+ // Clip
+ Rect clip = new Rect(20, 20, Utils.A4_WIDTH_PTS - 20, Utils.A4_HEIGHT_PTS - 20);
+
+ Utils.renderAndCompare(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS, Utils.A4_PORTRAIT, clip,
+ transform, Page.RENDER_MODE_FOR_DISPLAY, mContext);
+ }
+
+ @Test
+ public void renderStreched() throws Exception {
+ Utils.renderAndCompare(Utils.A4_WIDTH_PTS * 4 / 3, Utils.A4_HEIGHT_PTS * 3 / 4,
+ Utils.A4_PORTRAIT, null, null, Page.RENDER_MODE_FOR_DISPLAY, mContext);
+ }
+
+ @Test
+ public void renderWithClip() throws Exception {
+ Rect clip = new Rect(20, 20, Utils.A4_WIDTH_PTS - 50, Utils.A4_HEIGHT_PTS - 50);
+ Utils.renderAndCompare(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS,
+ Utils.A4_PORTRAIT, clip, null, Page.RENDER_MODE_FOR_DISPLAY, mContext);
+ }
+
+ @Test
+ public void renderWithAllClipped() throws Exception {
+ Rect clip = new Rect(Utils.A4_WIDTH_PTS / 2, Utils.A4_HEIGHT_PTS / 2,
+ Utils.A4_WIDTH_PTS / 2, Utils.A4_HEIGHT_PTS / 2);
+ Utils.renderAndCompare(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS, Utils.A4_PORTRAIT, clip,
+ null, Page.RENDER_MODE_FOR_DISPLAY, mContext);
+ }
+
+ @Test
+ public void renderWithBadLowerCornerOfClip() throws Exception {
+ Rect clip = new Rect(0, 0, Utils.A4_WIDTH_PTS + 20, Utils.A4_HEIGHT_PTS + 20);
+ assertException(() -> Utils
+ .renderWithTransform(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS,
+ Utils.A4_PORTRAIT, clip, null, Page.RENDER_MODE_FOR_DISPLAY,
+ mContext),
+ IllegalArgumentException.class);
+ }
+
+ @Test
+ public void renderWithBadUpperCornerOfClip() throws Exception {
+ Rect clip = new Rect(-20, -20, Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS);
+ assertException(() -> Utils
+ .renderWithTransform(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS,
+ Utils.A4_PORTRAIT, clip, null, Page.RENDER_MODE_FOR_DISPLAY,
+ mContext),
+ IllegalArgumentException.class);
+ }
+
+ @Test
+ public void renderTwoModes() throws Exception {
+ assertException(() -> Utils
+ .renderWithTransform(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS, Utils.A4_PORTRAIT,
+ null, null, Page.RENDER_MODE_FOR_DISPLAY | Page.RENDER_MODE_FOR_PRINT,
+ mContext), IllegalArgumentException.class);
+ }
+
+ @Test
+ public void renderBadMode() throws Exception {
+ assertException(() -> Utils
+ .renderWithTransform(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS, Utils.A4_PORTRAIT,
+ null, null, 1 << 30, mContext), IllegalArgumentException.class);
+ }
+
+ @Test
+ public void renderAllModes() throws Exception {
+ assertException(() -> Utils
+ .renderWithTransform(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS, Utils.A4_PORTRAIT,
+ null, null, -1, mContext), IllegalArgumentException.class);
+ }
+
+ @Test
+ public void renderNoMode() throws Exception {
+ assertException(() -> Utils
+ .renderWithTransform(Utils.A4_WIDTH_PTS, Utils.A4_HEIGHT_PTS, Utils.A4_PORTRAIT,
+ null, null, 0, mContext), IllegalArgumentException.class);
+ }
+
+ @Test
+ public void renderOnNullBitmap() throws Exception {
+ try (PdfRenderer renderer = Utils.createRenderer(Utils.A4_PORTRAIT, mContext)) {
+ try (Page page = renderer.openPage(0)) {
+ assertException(() -> page.render(null, null, null, Page.RENDER_MODE_FOR_DISPLAY),
+ NullPointerException.class);
+ }
+ }
+ }
+
+ /**
+ * A runnable that can throw an exception.
+ */
+ private interface Invokable {
+ void run() throws Exception;
+ }
+}
diff --git a/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTransformTest.java b/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTransformTest.java
new file mode 100644
index 0000000..facbd4e
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTransformTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.graphics.pdf.cts;
+
+import android.content.Context;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.pdf.PdfRenderer;
+import android.graphics.pdf.PdfRenderer.Page;
+import android.support.annotation.Nullable;
+import android.support.annotation.RawRes;
+import android.support.test.InstrumentationRegistry;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Test for the {@link PdfRenderer}
+ */
+@RunWith(Parameterized.class)
+public class PdfRendererTransformTest {
+ private Context mContext;
+ private int mWidth;
+ private int mHeight;
+ private int mDocRes;
+ private @Nullable Rect mClipping;
+ private @Nullable Matrix mTransformation;
+ private int mRenderMode;
+
+ public PdfRendererTransformTest(int width, int height, @RawRes int docRes,
+ @Nullable Rect clipping, @Nullable Matrix transformation, int renderMode) {
+ mWidth = width;
+ mHeight = height;
+ mDocRes = docRes;
+ mClipping = clipping;
+ mTransformation = transformation;
+ mRenderMode = renderMode;
+ }
+
+ @Parameterized.Parameters
+ public static Collection<Object[]> getParameters() {
+ int[] widths = new int[] { Utils.A4_WIDTH_PTS * 3 / 4, Utils.A4_WIDTH_PTS,
+ Utils.A4_WIDTH_PTS * 4 / 3
+ };
+ int[] heights = new int[] { Utils.A4_HEIGHT_PTS * 3 / 4, Utils.A4_HEIGHT_PTS,
+ Utils.A4_HEIGHT_PTS * 4 / 3
+ };
+ int[] rotations = new int[] { 0, 15, 90, 180 };
+ int[] translations = new int[] { -Utils.A4_HEIGHT_PTS / 2, 0, Utils.A4_HEIGHT_PTS / 2 };
+ float[] scales = { -0.5f, 0, 1, 1.5f };
+
+ Collection<Object[]> params = new ArrayList<>();
+
+ for (int rotation : rotations) {
+ for (float scaleX : scales) {
+ for (float scaleY : scales) {
+ for (int translateX : translations) {
+ for (int translateY : translations) {
+ Matrix transformation = new Matrix();
+ if (rotation != 0 || translateX != 0 || translateY != 0
+ || scaleX != 0 || scaleY != 0) {
+ if (rotation != 0) {
+ transformation.postRotate(rotation);
+ }
+
+ if (scaleX != 0 || scaleY != 0) {
+ transformation.postScale(scaleX, scaleY);
+ }
+
+ if (translateX != 0 || translateY != 0) {
+ transformation.postTranslate(translateX,
+ translateY);
+ }
+ }
+
+ for (int width : widths) {
+ for (int height : heights) {
+ params.add(
+ new Object[] { width, height, Utils.A4_PORTRAIT, null,
+ transformation, Page.RENDER_MODE_FOR_DISPLAY
+ });
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return params;
+ }
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ }
+
+ @Test
+ public void test() throws Exception {
+ Utils.renderAndCompare(mWidth, mHeight, mDocRes, mClipping, mTransformation, mRenderMode,
+ mContext);
+ }
+}
diff --git a/tests/tests/graphics/src/android/graphics/pdf/cts/Utils.java b/tests/tests/graphics/src/android/graphics/pdf/cts/Utils.java
new file mode 100644
index 0000000..402a99f
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/pdf/cts/Utils.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.graphics.pdf.cts;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.pdf.PdfRenderer;
+import android.os.ParcelFileDescriptor;
+import android.support.annotation.FloatRange;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.RawRes;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Map;
+
+import static org.junit.Assert.fail;
+
+/**
+ * Utilities for this package
+ */
+class Utils {
+ private static final String LOG_TAG = "Utils";
+
+ static final int A4_WIDTH_PTS = 595;
+ static final int A4_HEIGHT_PTS = 841;
+ static final int A4_PORTRAIT = android.graphics.cts.R.raw.a4_portrait_rgbb;
+ static final int A5_PORTRAIT = android.graphics.cts.R.raw.a5_portrait_rgbb;
+
+ private static Map<Integer, File> sFiles = new ArrayMap<>();
+ private static Map<Integer, Bitmap> sRenderedBitmaps = new ArrayMap<>();
+
+ /**
+ * Create a {@link PdfRenderer} pointing to a file copied from a resource.
+ *
+ * @param docRes The resource to load
+ * @param context The context to use for creating the renderer
+ *
+ * @return the renderer
+ *
+ * @throws IOException If anything went wrong
+ */
+ static @NonNull PdfRenderer createRenderer(@RawRes int docRes, @NonNull Context context)
+ throws IOException {
+ File pdfFile = sFiles.get(docRes);
+
+ if (pdfFile == null) {
+ pdfFile = File.createTempFile("pdf", null, context.getCacheDir());
+
+ // Copy resource to file so that we can open it as a ParcelFileDescriptor
+ try (OutputStream os = new BufferedOutputStream(new FileOutputStream(pdfFile))) {
+ try (InputStream is = new BufferedInputStream(
+ context.getResources().openRawResource(docRes))) {
+ byte buffer[] = new byte[1024];
+
+ while (true) {
+ int numRead = is.read(buffer, 0, buffer.length);
+
+ if (numRead == -1) {
+ break;
+ }
+
+ os.write(Arrays.copyOf(buffer, numRead));
+ }
+
+ os.flush();
+ }
+ }
+
+ sFiles.put(docRes, pdfFile);
+ }
+
+ return new PdfRenderer(
+ ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY));
+ }
+
+ /**
+ * Render a pdf onto a bitmap <u>while</u> applying the transformation <u>in the</u>
+ * PDFRenderer. Hence use PdfRenderer.*'s translation and clipping methods.
+ *
+ * @param bmWidth The width of the destination bitmap
+ * @param bmHeight The height of the destination bitmap
+ * @param docRes The resolution of the doc
+ * @param clipping The clipping for the PDF document
+ * @param transformation The transformation of the PDF
+ * @param renderMode The render mode to use to render the PDF
+ * @param context The context to use for creating the renderer
+ *
+ * @return The rendered bitmap
+ */
+ static @NonNull Bitmap renderWithTransform(int bmWidth, int bmHeight, @RawRes int docRes,
+ @Nullable Rect clipping, @Nullable Matrix transformation, int renderMode,
+ @NonNull Context context)
+ throws IOException {
+ try (PdfRenderer renderer = createRenderer(docRes, context)) {
+ try (PdfRenderer.Page page = renderer.openPage(0)) {
+ Bitmap bm = Bitmap.createBitmap(bmWidth, bmHeight, Bitmap.Config.ARGB_8888);
+
+ page.render(bm, clipping, transformation, renderMode);
+
+ return bm;
+ }
+ }
+ }
+
+ /**
+ * Render a pdf onto a bitmap <u>and then</u> apply then render the resulting bitmap onto
+ * another bitmap while applying the transformation. Hence use canvas' translation and clipping
+ * methods.
+ *
+ * @param bmWidth The width of the destination bitmap
+ * @param bmHeight The height of the destination bitmap
+ * @param docRes The resolution of the doc
+ * @param clipping The clipping for the PDF document
+ * @param transformation The transformation of the PDF
+ * @param renderMode The render mode to use to render the PDF
+ * @param context The context to use for creating the renderer
+ *
+ * @return The rendered bitmap
+ */
+ private static @NonNull Bitmap renderAndThenTransform(int bmWidth, int bmHeight,
+ @RawRes int docRes, @Nullable Rect clipping, @Nullable Matrix transformation,
+ int renderMode, @NonNull Context context) throws IOException {
+ Bitmap renderedBm;
+
+ renderedBm = sRenderedBitmaps.get(docRes);
+
+ if (renderedBm == null) {
+ try (PdfRenderer renderer = Utils.createRenderer(docRes, context)) {
+ try (PdfRenderer.Page page = renderer.openPage(0)) {
+ renderedBm = Bitmap.createBitmap(page.getWidth(), page.getHeight(),
+ Bitmap.Config.ARGB_8888);
+ page.render(renderedBm, null, null, renderMode);
+ }
+ }
+ sRenderedBitmaps.put(docRes, renderedBm);
+ }
+
+ if (transformation == null) {
+ // According to PdfRenderer.page#render transformation == null means that the bitmap
+ // should be stretched to clipping (if provided) or otherwise destination size
+ transformation = new Matrix();
+
+ if (clipping != null) {
+ transformation.postScale((float) clipping.width() / renderedBm.getWidth(),
+ (float) clipping.height() / renderedBm.getHeight());
+ transformation.postTranslate(clipping.left, clipping.top);
+ } else {
+ transformation.postScale((float) bmWidth / renderedBm.getWidth(),
+ (float) bmHeight / renderedBm.getHeight());
+ }
+ }
+
+ Bitmap transformedBm = Bitmap.createBitmap(bmWidth, bmHeight, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(transformedBm);
+ canvas.drawBitmap(renderedBm, transformation, null);
+
+ Bitmap clippedBm;
+ if (clipping != null) {
+ clippedBm = Bitmap.createBitmap(bmWidth, bmHeight, Bitmap.Config.ARGB_8888);
+ canvas = new Canvas(clippedBm);
+ canvas.drawBitmap(transformedBm, clipping, clipping, null);
+ transformedBm.recycle();
+ } else {
+ clippedBm = transformedBm;
+ }
+
+ return clippedBm;
+ }
+
+ /**
+ * Get the fraction of non-matching pixels of two bitmaps. 1 == no pixels match, 0 == all pixels
+ * match.
+ *
+ * @param a The first bitmap
+ * @param b The second bitmap
+ *
+ * @return The fraction of non-matching pixels.
+ */
+ private static @FloatRange(from = 0, to = 1) float getNonMatching(@NonNull Bitmap a,
+ @NonNull Bitmap b) {
+ if (a.getWidth() != b.getWidth() || a.getHeight() != b.getHeight()) {
+ return 1;
+ }
+
+ int[] aPx = new int[a.getWidth() * a.getHeight()];
+ int[] bPx = new int[b.getWidth() * b.getHeight()];
+ a.getPixels(aPx, 0, a.getWidth(), 0, 0, a.getWidth(), a.getHeight());
+ b.getPixels(bPx, 0, b.getWidth(), 0, 0, b.getWidth(), b.getHeight());
+
+ int badPixels = 0;
+ for (int i = 0; i < a.getWidth() * a.getHeight(); i++) {
+ if (aPx[i] != bPx[i]) {
+ badPixels++;
+ }
+ }
+
+ return ((float) badPixels) / (a.getWidth() * a.getHeight());
+ }
+
+ /**
+ * Render the PDF two times. Once with applying the transformation and clipping in the {@link
+ * PdfRenderer}. The other time render the PDF onto a bitmap and then clip and transform that
+ * image. The result should be the same beside some minor aliasing.
+ *
+ * @param width The width of the resulting bitmap
+ * @param height The height of the resulting bitmap
+ * @param docRes The resource of the PDF document
+ * @param clipping The clipping to apply
+ * @param transformation The transformation to apply
+ * @param renderMode The render mode to use
+ * @param context The context to use for creating the renderer
+ *
+ * @throws IOException
+ */
+ static void renderAndCompare(int width, int height, @RawRes int docRes,
+ @Nullable Rect clipping, @Nullable Matrix transformation, int renderMode,
+ @NonNull Context context) throws IOException {
+ Bitmap a = renderWithTransform(width, height, docRes, clipping, transformation,
+ renderMode, context);
+ Bitmap b = renderAndThenTransform(width, height, docRes, clipping, transformation,
+ renderMode, context);
+
+ try {
+ // We allow 1% aliasing error
+ float nonMatching = getNonMatching(a, b);
+
+ if (nonMatching == 0) {
+ Log.d(LOG_TAG, "bitmaps match");
+ } else if (nonMatching > 0.01) {
+ fail("Testing width:" + width + ", height:" + height + ", docRes:" + docRes +
+ ", clipping:" + clipping + ", transform:" + transformation + ". Bitmaps " +
+ "differ by " + Math.ceil(nonMatching * 10000) / 100 +
+ "%. That is too much.");
+ } else {
+ Log.d(LOG_TAG, "bitmaps differ by " + Math.ceil(nonMatching * 10000) / 100 + "%");
+ }
+ } finally {
+ a.recycle();
+ b.recycle();
+ }
+ }
+}
diff --git a/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java b/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
index 77c6da1..5a76816 100644
--- a/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
+++ b/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
@@ -25,6 +25,7 @@
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.microedition.khronos.egl.EGL10;
@@ -61,20 +62,16 @@
int detectedMajorVersion = getDetectedMajorVersion();
int reportedVersion = getVersionFromActivityManager(mActivity);
- assertEquals("Detected OpenGL ES major version " + detectedMajorVersion
- + " but Activity Manager is reporting " + getMajorVersion(reportedVersion)
- + " (Check ro.opengles.version)",
- detectedMajorVersion, getMajorVersion(reportedVersion));
assertEquals("Reported OpenGL ES version from ActivityManager differs from PackageManager",
reportedVersion, getVersionFromPackageManager(mActivity));
- assertGlVersionString(1);
+ assertGlVersionString(1, 1);
if (detectedMajorVersion == 2) {
restartActivityWithClientVersion(2);
- assertGlVersionString(2);
+ assertGlVersionString(2, getMinorVersion(reportedVersion));
} else if (detectedMajorVersion == 3) {
restartActivityWithClientVersion(3);
- assertGlVersionString(3);
+ assertGlVersionString(3, getMinorVersion(reportedVersion));
}
}
@@ -123,14 +120,11 @@
restartActivityWithClientVersion(3);
String extensions = mActivity.getExtensionsString();
- if (!hasExtension(extensions, "ANDROID_extension_pack_es31a")) {
- assertFalse("FEATURE_OPENGLES_EXTENSION_PACK is available but ANDROID_extension_pack_es31a isn't in the extension list",
- hasAepFeature);
- return;
- }
-
- assertTrue("ANDROID_extension_pack_es31a is present, but support is incomplete",
- mActivity.getAepEs31Support());
+ boolean hasAepExtension = hasExtension(extensions, "GL_ANDROID_extension_pack_es31a");
+ assertEquals("System feature FEATURE_OPENGLES_EXTENSION_PACK is "
+ + (hasAepFeature ? "" : "not ") + "available, but extension GL_ANDROID_extension_pack_es31a is "
+ + (hasAepExtension ? "" : "not ") + "in the OpenGL ES extension list.",
+ hasAepFeature, hasAepExtension);
}
public void testOpenGlEsVersionForVrHighPerformance() throws InterruptedException {
@@ -288,15 +282,21 @@
}
/**
- * Check that the version string has some form of "Open GL ES X.Y" in it where X is the major
- * version and Y must be some digit.
+ * Check that the version string has the form "OpenGL ES(-CM)? (\d+)\.(\d+)", where the two
+ * numbers match the major and minor parameters.
*/
- private void assertGlVersionString(int majorVersion) throws InterruptedException {
- String versionString = "" + majorVersion;
- String message = "OpenGL version string '" + mActivity.getVersionString()
- + "' is not " + majorVersion + ".0+.";
- assertTrue(message, Pattern.matches(".*OpenGL.*ES.*" + versionString + "\\.\\d.*",
- mActivity.getVersionString()));
+ private void assertGlVersionString(int major, int minor) throws InterruptedException {
+ Matcher matcher = Pattern.compile("OpenGL ES(?:-CM)? (\\d+)\\.(\\d+).*")
+ .matcher(mActivity.getVersionString());
+ assertTrue("OpenGL ES version string is not of the required form "
+ + "'OpenGL ES(-CM)? (\\d+)\\.(\\d+).*'",
+ matcher.matches());
+ int stringMajor = Integer.parseInt(matcher.group(1));
+ int stringMinor = Integer.parseInt(matcher.group(2));
+ assertEquals("GL_VERSION string doesn't match ActivityManager major version (check ro.opengles.version property)",
+ major, stringMajor);
+ assertEquals("GL_VERSION string doesn't match ActivityManager minor version (check ro.opengles.version property)",
+ minor, stringMinor);
}
/** Restart {@link GLSurfaceViewCtsActivity} with a specific client version. */
diff --git a/tests/tests/icu/Android.mk b/tests/tests/icu/Android.mk
index 6f183d5..39d1285 100644
--- a/tests/tests/icu/Android.mk
+++ b/tests/tests/icu/Android.mk
@@ -30,9 +30,12 @@
# The aim of this package is to run tests against the implementation in use by
# the current android system.
+LOCAL_JAVA_LIBRARIES := cts-core-test-runner
+
LOCAL_STATIC_JAVA_LIBRARIES := \
- cts-core-test-runner \
- android-icu4j-tests
+ android-icu4j-tests \
+ ctstestrunner \
+ android-support-test
# Tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/tests/tests/jni/Android.mk b/tests/tests/jni/Android.mk
index 7a9504d..4a81a85 100644
--- a/tests/tests/jni/Android.mk
+++ b/tests/tests/jni/Android.mk
@@ -30,7 +30,7 @@
# Tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
LOCAL_JNI_SHARED_LIBRARIES := libjnitest libnativehelper_compat_libc++
diff --git a/tests/tests/jni/libjnitest/helper.c b/tests/tests/jni/libjnitest/helper.c
index 8f7f2f8..2281795 100644
--- a/tests/tests/jni/libjnitest/helper.c
+++ b/tests/tests/jni/libjnitest/helper.c
@@ -70,6 +70,7 @@
free(result);
if (newResult == NULL) {
// Shouldn't happen, but deal as gracefully as possible.
+ va_end(args);
return NULL;
}
result = newResult;
diff --git a/tests/tests/jni/libjnitest/macroized_tests.c b/tests/tests/jni/libjnitest/macroized_tests.c
index 76b5481..130b378 100644
--- a/tests/tests/jni/libjnitest/macroized_tests.c
+++ b/tests/tests/jni/libjnitest/macroized_tests.c
@@ -192,6 +192,7 @@
"returnBoolean", "()Z");
if (method == NULL) {
+ va_end(args);
return msg;
}
@@ -240,6 +241,7 @@
break;
}
default: {
+ va_end(args);
return failure("shouldn't happen");
}
}
@@ -295,6 +297,7 @@
"returnByte", "()B");
if (method == NULL) {
+ va_end(args);
return msg;
}
@@ -343,6 +346,7 @@
break;
}
default: {
+ va_end(args);
return failure("shouldn't happen");
}
}
@@ -398,6 +402,7 @@
"returnShort", "()S");
if (method == NULL) {
+ va_end(args);
return msg;
}
@@ -446,6 +451,7 @@
break;
}
default: {
+ va_end(args);
return failure("shouldn't happen");
}
}
@@ -501,6 +507,7 @@
"returnChar", "()C");
if (method == NULL) {
+ va_end(args);
return msg;
}
@@ -549,6 +556,7 @@
break;
}
default: {
+ va_end(args);
return failure("shouldn't happen");
}
}
@@ -604,6 +612,7 @@
"returnInt", "()I");
if (method == NULL) {
+ va_end(args);
return msg;
}
@@ -652,6 +661,7 @@
break;
}
default: {
+ va_end(args);
return failure("shouldn't happen");
}
}
@@ -707,6 +717,7 @@
"returnLong", "()J");
if (method == NULL) {
+ va_end(args);
return msg;
}
@@ -755,6 +766,7 @@
break;
}
default: {
+ va_end(args);
return failure("shouldn't happen");
}
}
@@ -810,6 +822,7 @@
"returnFloat", "()F");
if (method == NULL) {
+ va_end(args);
return msg;
}
@@ -858,6 +871,7 @@
break;
}
default: {
+ va_end(args);
return failure("shouldn't happen");
}
}
@@ -913,6 +927,7 @@
"returnDouble", "()D");
if (method == NULL) {
+ va_end(args);
return msg;
}
@@ -961,6 +976,7 @@
break;
}
default: {
+ va_end(args);
return failure("shouldn't happen");
}
}
@@ -1016,6 +1032,7 @@
"nop", "()V");
if (method == NULL) {
+ va_end(args);
return msg;
}
@@ -1064,6 +1081,7 @@
break;
}
default: {
+ va_end(args);
return failure("shouldn't happen");
}
}
@@ -1119,6 +1137,7 @@
"returnString", "()Ljava/lang/String;");
if (method == NULL) {
+ va_end(args);
return msg;
}
@@ -1171,6 +1190,7 @@
break;
}
default: {
+ va_end(args);
return failure("shouldn't happen");
}
}
@@ -1240,6 +1260,7 @@
"takeOneOfEach", "(DFJICSBZLjava/lang/String;)Z");
if (method == NULL) {
+ va_end(args);
return msg;
}
@@ -1299,6 +1320,7 @@
break;
}
default: {
+ va_end(args);
return failure("shouldn't happen");
}
}
@@ -1361,6 +1383,7 @@
"(IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII)Z");
if (method == NULL) {
+ va_end(args);
return msg;
}
@@ -1441,6 +1464,7 @@
break;
}
default: {
+ va_end(args);
return failure("shouldn't happen");
}
}
diff --git a/tests/tests/keystore/Android.mk b/tests/tests/keystore/Android.mk
index 4688846..8fe7a3b 100644
--- a/tests/tests/keystore/Android.mk
+++ b/tests/tests/keystore/Android.mk
@@ -26,6 +26,7 @@
LOCAL_JAVA_LIBRARIES := bouncycastle
LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-test \
core-tests-support \
ctsdeviceutil \
ctstestrunner \
diff --git a/tests/tests/media/Android.mk b/tests/tests/media/Android.mk
index eda78e8..d61556d 100644
--- a/tests/tests/media/Android.mk
+++ b/tests/tests/media/Android.mk
@@ -44,7 +44,7 @@
# include both the 32 and 64 bit versions
LOCAL_MULTILIB := both
-LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil ctsdeviceutil compatibility-device-util ctstestserver ctstestrunner ndkaudio
+LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil ctsdeviceutil compatibility-device-util ctstestserver ctstestrunner ndkaudio android-support-test
LOCAL_JNI_SHARED_LIBRARIES := libctsmediacodec_jni libaudio_jni libnativehelper_compat_libc++ libndkaudioLib
diff --git a/tests/tests/media/src/android/media/cts/IvfWriter.java b/tests/tests/media/src/android/media/cts/IvfWriter.java
index 075f73c..36fb679 100644
--- a/tests/tests/media/src/android/media/cts/IvfWriter.java
+++ b/tests/tests/media/src/android/media/cts/IvfWriter.java
@@ -16,6 +16,8 @@
package android.media.cts;
+import android.media.MediaFormat;
+
import java.io.IOException;
import java.io.RandomAccessFile;
@@ -34,6 +36,7 @@
private int mScale;
private int mRate;
private int mFrameCount;
+ private String mMimeType;
/**
* Initializes the IVF file writer.
@@ -43,15 +46,17 @@
* with this timebase value.
*
* @param filename name of the IVF file
+ * @param mimeType mime type of the codec
* @param width frame width
* @param height frame height
* @param scale timebase scale (or numerator of the timebase fraction)
* @param rate timebase rate (or denominator of the timebase fraction)
*/
- public IvfWriter(String filename,
- int width, int height,
- int scale, int rate) throws IOException {
+ public IvfWriter(
+ String filename, String mimeType, int width, int height, int scale,
+ int rate) throws IOException {
mOutputFile = new RandomAccessFile(filename, "rw");
+ mMimeType = mimeType;
mWidth = width;
mHeight = height;
mScale = scale;
@@ -67,11 +72,12 @@
* Microsecond timebase is default for OMX thus stagefright.
*
* @param filename name of the IVF file
+ * @param mimeType mime type of the codec
* @param width frame width
* @param height frame height
*/
- public IvfWriter(String filename, int width, int height) throws IOException {
- this(filename, width, height, 1, 1000000);
+ public IvfWriter(String filename, String mimeType, int width, int height) throws IOException {
+ this(filename, mimeType, width, height, 1, 1000000);
}
/**
@@ -80,7 +86,7 @@
public void close() throws IOException{
// Write header now
mOutputFile.seek(0);
- mOutputFile.write(makeIvfHeader(mFrameCount, mWidth, mHeight, mScale, mRate));
+ mOutputFile.write(makeIvfHeader(mFrameCount, mWidth, mHeight, mScale, mRate, mMimeType));
mOutputFile.close();
}
@@ -107,7 +113,8 @@
* @param scale timebase scale (or numerator of the timebase fraction)
* @param rate timebase rate (or denominator of the timebase fraction)
*/
- private static byte[] makeIvfHeader(int frameCount, int width, int height, int scale, int rate){
+ private static byte[] makeIvfHeader(
+ int frameCount, int width, int height, int scale, int rate, String mimeType) {
byte[] ivfHeader = new byte[32];
ivfHeader[0] = 'D';
ivfHeader[1] = 'K';
@@ -117,7 +124,7 @@
lay16Bits(ivfHeader, 6, 32); // header size
ivfHeader[8] = 'V'; // fourcc
ivfHeader[9] = 'P';
- ivfHeader[10] = '8';
+ ivfHeader[10] = (byte) (MediaFormat.MIMETYPE_VIDEO_VP8.equals(mimeType) ? '8' : '9');
ivfHeader[11] = '0';
lay16Bits(ivfHeader, 12, width);
lay16Bits(ivfHeader, 14, height);
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
index 5b2936b..b579c6d 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
@@ -52,12 +52,8 @@
private static final int TIMEOUT_US = 1000000; // 1 sec
private static final int IFRAME_INTERVAL = 10; // 10 seconds between I-frames
- private final MediaCodecList mRegularCodecs =
- new MediaCodecList(MediaCodecList.REGULAR_CODECS);
private final MediaCodecList mAllCodecs =
new MediaCodecList(MediaCodecList.ALL_CODECS);
- private final MediaCodecInfo[] mRegularInfos =
- mRegularCodecs.getCodecInfos();
private final MediaCodecInfo[] mAllInfos =
mAllCodecs.getCodecInfos();
@@ -391,7 +387,7 @@
// check if there is an adaptive decoder for each
for (String mime : supportedFormats) {
skipped = false;
- // implicit assumption that QVGA video is always valid.
+ // implicit assumption that QCIF video is always valid.
MediaFormat format = MediaFormat.createVideoFormat(mime, 176, 144);
format.setFeatureEnabled(CodecCapabilities.FEATURE_AdaptivePlayback, true);
String codec = mAllCodecs.findDecoderForFormat(format);
@@ -501,7 +497,7 @@
MediaFormat format = null;
try {
codec = MediaCodec.createByCodecName(info.getName());
- // implicit assumption that QVGA video is always valid.
+ // implicit assumption that QCIF video is always valid.
format = createReasonableVideoFormat(caps, mime, isEncoder, 176, 144);
format.setInteger(
MediaFormat.KEY_COLOR_FORMAT,
diff --git a/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java b/tests/tests/media/src/android/media/cts/VpxCodecTestBase.java
similarity index 96%
rename from tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
rename to tests/tests/media/src/android/media/cts/VpxCodecTestBase.java
index 0395ec7..ea72225 100644
--- a/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
+++ b/tests/tests/media/src/android/media/cts/VpxCodecTestBase.java
@@ -43,17 +43,18 @@
import java.util.concurrent.CountDownLatch;
/**
- * Verification test for vp8 encoder and decoder.
+ * Verification test for vpx encoder and decoder.
*
* A raw yv12 stream is encoded at various settings and written to an IVF
* file. Encoded stream bitrate and key frame interval are checked against target values.
- * The stream is later decoded by vp8 decoder to verify frames are decodable and to
+ * The stream is later decoded by the decoder to verify frames are decodable and to
* calculate PSNR values for various bitrates.
*/
-public class Vp8CodecTestBase extends AndroidTestCase {
+public class VpxCodecTestBase extends AndroidTestCase {
- protected static final String TAG = "VP8CodecTestBase";
+ protected static final String TAG = "VPxCodecTestBase";
protected static final String VP8_MIME = MediaFormat.MIMETYPE_VIDEO_VP8;
+ protected static final String VP9_MIME = MediaFormat.MIMETYPE_VIDEO_VP9;
private static final String GOOGLE_CODEC_PREFIX = "omx.google.";
protected static final String SDCARD_DIR =
Environment.getExternalStorageDirectory().getAbsolutePath();
@@ -91,7 +92,7 @@
}
/**
- * VP8 codec properties generated by getVp8CodecProperties() function.
+ * VPx codec properties generated by getVpxCodecProperties() function.
*/
private class CodecProperties {
CodecProperties(String codecName, int colorFormat) {
@@ -102,12 +103,12 @@
return codecName.toLowerCase().startsWith(GOOGLE_CODEC_PREFIX);
}
- public final String codecName; // OpenMax component name for VP8 codec.
+ public final String codecName; // OpenMax component name for VPx codec.
public final int colorFormat; // Color format supported by codec.
}
/**
- * Function to find VP8 codec.
+ * Function to find VPx codec.
*
* Iterates through the list of available codecs and tries to find
* VPX codec, which can support either YUV420 planar or NV12 color formats.
@@ -197,7 +198,9 @@
int inputResourceId;
// Name of the IVF file to write encoded bitsream
public String outputIvfFilename;
- // Force to use Google VP8 encoder.
+ // Mime Type of the Encoded content.
+ public String codecMimeType;
+ // Force to use Google VPx encoder.
boolean forceGoogleEncoder;
// Number of frames to encode.
int frameCount;
@@ -236,6 +239,7 @@
protected ArrayList<EncoderOutputStreamParameters> getDefaultEncodingParameterList(
String inputYuvName,
String outputIvfBaseName,
+ String codecMimeType,
int encodeSeconds,
int[] resolutionScales,
int frameWidth,
@@ -258,8 +262,10 @@
params.scaledYuvFilename = SDCARD_DIR + File.separator +
outputIvfBaseName + resolutionScales[i]+ ".yuv";
params.inputResourceId = R.raw.football_qvga;
+ params.codecMimeType = codecMimeType;
+ String codecSuffix = VP8_MIME.equals(codecMimeType) ? "vp8" : "vp9";
params.outputIvfFilename = SDCARD_DIR + File.separator +
- outputIvfBaseName + resolutionScales[i] + ".ivf";
+ outputIvfBaseName + resolutionScales[i] + "_" + codecSuffix + ".ivf";
params.forceGoogleEncoder = false;
params.frameCount = encodeSeconds * frameRate;
params.frameRate = frameRate;
@@ -286,6 +292,7 @@
protected EncoderOutputStreamParameters getDefaultEncodingParameters(
String inputYuvName,
String outputIvfBaseName,
+ String codecMimeType,
int encodeSeconds,
int frameWidth,
int frameHeight,
@@ -298,6 +305,7 @@
return getDefaultEncodingParameterList(
inputYuvName,
outputIvfBaseName,
+ codecMimeType,
encodeSeconds,
scaleValues,
frameWidth,
@@ -500,17 +508,18 @@
* md5 sum comparison wouldn't work.)
*
* Indeed, MediaCodec will raise an IllegalStateException
- * whenever vp8 decoder fails to decode a frame, and
+ * whenever vpx decoder fails to decode a frame, and
* this test uses that fact to verify the bitstream.
*
* @param inputIvfFilename The name of the IVF file containing encoded bitsream.
* @param outputYuvFilename The name of the output YUV file (optional).
* @param frameRate Frame rate of input file in frames per second
- * @param forceGoogleDecoder Force to use Google VP8 decoder.
+ * @param forceGoogleDecoder Force to use Google VPx decoder.
*/
protected ArrayList<MediaCodec.BufferInfo> decode(
String inputIvfFilename,
String outputYuvFilename,
+ String codecMimeType,
int frameRate,
boolean forceGoogleDecoder) throws Exception {
ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
@@ -528,7 +537,7 @@
// Create decoder.
MediaFormat format = MediaFormat.createVideoFormat(
- VP8_MIME, ivf.getWidth(), ivf.getHeight());
+ codecMimeType, ivf.getWidth(), ivf.getHeight());
CodecProperties properties = getVpxCodecProperties(
false /* encoder */, format, forceGoogleDecoder);
if (properties == null) {
@@ -1243,13 +1252,13 @@
}
/**
- * Vp8 encoding loop supporting encoding single streams with an option
+ * Vpx encoding loop supporting encoding single streams with an option
* to run in a looper thread and use buffer ready notification callbacks.
*
* Output stream is described by encodingParams parameters.
*
* MediaCodec will raise an IllegalStateException
- * whenever vp8 encoder fails to encode a frame.
+ * whenever vpx encoder fails to encode a frame.
*
* Color format of input file should be YUV420, and frameWidth,
* frameHeight should be supplied correctly as raw input file doesn't
@@ -1268,7 +1277,8 @@
// Create minimal media format signifying desired output.
MediaFormat format = MediaFormat.createVideoFormat(
- VP8_MIME, streamParams.frameWidth, streamParams.frameHeight);
+ streamParams.codecMimeType, streamParams.frameWidth,
+ streamParams.frameHeight);
format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
CodecProperties properties = getVpxCodecProperties(
true, format, streamParams.forceGoogleEncoder);
@@ -1280,7 +1290,8 @@
InputStream yuvStream = OpenFileOrResourceId(
streamParams.inputYuvFilename, streamParams.inputResourceId);
IvfWriter ivf = new IvfWriter(
- streamParams.outputIvfFilename, streamParams.frameWidth, streamParams.frameHeight);
+ streamParams.outputIvfFilename, streamParams.codecMimeType,
+ streamParams.frameWidth, streamParams.frameHeight);
// Create a media format signifying desired output.
if (streamParams.bitrateType == VIDEO_ControlRateConstant) {
@@ -1416,12 +1427,12 @@
}
/**
- * Vp8 encoding run in a looper thread and use buffer ready callbacks.
+ * Vpx encoding run in a looper thread and use buffer ready callbacks.
*
* Output stream is described by encodingParams parameters.
*
* MediaCodec will raise an IllegalStateException
- * whenever vp8 encoder fails to encode a frame.
+ * whenever vpx encoder fails to encode a frame.
*
* Color format of input file should be YUV420, and frameWidth,
* frameHeight should be supplied correctly as raw input file doesn't
@@ -1443,7 +1454,8 @@
// Create minimal media format signifying desired output.
MediaFormat format = MediaFormat.createVideoFormat(
- VP8_MIME, streamParams.frameWidth, streamParams.frameHeight);
+ streamParams.codecMimeType, streamParams.frameWidth,
+ streamParams.frameHeight);
format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
CodecProperties properties = getVpxCodecProperties(
true, format, streamParams.forceGoogleEncoder);
@@ -1453,7 +1465,8 @@
// Open input/output
IvfWriter ivf = new IvfWriter(
- streamParams.outputIvfFilename, streamParams.frameWidth, streamParams.frameHeight);
+ streamParams.outputIvfFilename, streamParams.codecMimeType,
+ streamParams.frameWidth, streamParams.frameHeight);
// Create a media format signifying desired output.
if (streamParams.bitrateType == VIDEO_ControlRateConstant) {
@@ -1495,13 +1508,13 @@
}
/**
- * Vp8 encoding loop supporting encoding multiple streams at a time.
+ * Vpx encoding loop supporting encoding multiple streams at a time.
* Each output stream is described by encodingParams parameters allowing
* simultaneous encoding of various resolutions, bitrates with an option to
* control key frame and dynamic bitrate for each output stream indepandently.
*
* MediaCodec will raise an IllegalStateException
- * whenever vp8 encoder fails to encode a frame.
+ * whenever vpx encoder fails to encode a frame.
*
* Color format of input file should be YUV420, and frameWidth,
* frameHeight should be supplied correctly as raw input file doesn't
@@ -1546,8 +1559,9 @@
int bitrate = params.bitrateSet[0];
// Create minimal media format signifying desired output.
- format[i] = MediaFormat.createVideoFormat(VP8_MIME,
- params.frameWidth, params.frameHeight);
+ format[i] = MediaFormat.createVideoFormat(
+ params.codecMimeType, params.frameWidth,
+ params.frameHeight);
format[i].setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
CodecProperties properties = getVpxCodecProperties(
true, format[i], params.forceGoogleEncoder);
@@ -1572,7 +1586,9 @@
yuvStream[i] = new FileInputStream(params.scaledYuvFilename);
// Create IVF writer
- ivf[i] = new IvfWriter(params.outputIvfFilename, params.frameWidth, params.frameHeight);
+ ivf[i] = new IvfWriter(
+ params.outputIvfFilename, params.codecMimeType,
+ params.frameWidth, params.frameHeight);
// Frame buffer
int frameSize = params.frameWidth * params.frameHeight * 3 / 2;
@@ -1731,8 +1747,8 @@
/**
* Some encoding statistics.
*/
- protected class Vp8EncodingStatistics {
- Vp8EncodingStatistics() {
+ protected class VpxEncodingStatistics {
+ VpxEncodingStatistics() {
mBitrates = new ArrayList<Integer>();
mFrames = new ArrayList<Integer>();
mKeyFrames = new ArrayList<Integer>();
@@ -1756,9 +1772,9 @@
* mKeyFrames array will contain the position of key frames in the encoded stream and
* mKeyFrameInterval - average key frame interval.
*/
- protected Vp8EncodingStatistics computeEncodingStatistics(int encoderId,
+ protected VpxEncodingStatistics computeEncodingStatistics(int encoderId,
ArrayList<MediaCodec.BufferInfo> bufferInfos ) {
- Vp8EncodingStatistics statistics = new Vp8EncodingStatistics();
+ VpxEncodingStatistics statistics = new VpxEncodingStatistics();
int totalSize = 0;
int frames = 0;
@@ -1838,18 +1854,18 @@
return statistics;
}
- protected Vp8EncodingStatistics computeEncodingStatistics(
+ protected VpxEncodingStatistics computeEncodingStatistics(
ArrayList<MediaCodec.BufferInfo> bufferInfos ) {
return computeEncodingStatistics(0, bufferInfos);
}
- protected ArrayList<Vp8EncodingStatistics> computeSimulcastEncodingStatistics(
+ protected ArrayList<VpxEncodingStatistics> computeSimulcastEncodingStatistics(
ArrayList<ArrayList<MediaCodec.BufferInfo>> bufferInfos) {
int numCodecs = bufferInfos.size();
- ArrayList<Vp8EncodingStatistics> statistics = new ArrayList<Vp8EncodingStatistics>();
+ ArrayList<VpxEncodingStatistics> statistics = new ArrayList<VpxEncodingStatistics>();
for (int i = 0; i < numCodecs; i++) {
- Vp8EncodingStatistics currentStatistics =
+ VpxEncodingStatistics currentStatistics =
computeEncodingStatistics(i, bufferInfos.get(i));
statistics.add(currentStatistics);
}
@@ -1872,8 +1888,8 @@
/**
* Decoding PSNR statistics.
*/
- protected class Vp8DecodingStatistics {
- Vp8DecodingStatistics() {
+ protected class VpxDecodingStatistics {
+ VpxDecodingStatistics() {
mMinimumPSNR = Integer.MAX_VALUE;
}
public double mAveragePSNR;
@@ -1901,13 +1917,13 @@
* set of reference and decoded video frames.
* Runs PSNR calculation for the full duration of the decoded data.
*/
- protected Vp8DecodingStatistics computeDecodingStatistics(
+ protected VpxDecodingStatistics computeDecodingStatistics(
String referenceYuvFilename,
int referenceYuvRawId,
String decodedYuvFilename,
int width,
int height) throws Exception {
- Vp8DecodingStatistics statistics = new Vp8DecodingStatistics();
+ VpxDecodingStatistics statistics = new VpxDecodingStatistics();
InputStream referenceStream =
OpenFileOrResourceId(referenceYuvFilename, referenceYuvRawId);
InputStream decodedStream = new FileInputStream(decodedYuvFilename);
diff --git a/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java b/tests/tests/media/src/android/media/cts/VpxEncoderTest.java
similarity index 85%
rename from tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
rename to tests/tests/media/src/android/media/cts/VpxEncoderTest.java
index 5552f6c..0e9c940 100644
--- a/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/VpxEncoderTest.java
@@ -28,14 +28,14 @@
import java.util.Arrays;
/**
- * Verification test for vp8 encoder and decoder.
+ * Verification test for vp8/vp9 encoder and decoder.
*
* A raw yv12 stream is encoded at various settings and written to an IVF
* file. Encoded stream bitrate and key frame interval are checked against target values.
- * The stream is later decoded by vp8 decoder to verify frames are decodable and to
+ * The stream is later decoded by vp8/vp9 decoder to verify frames are decodable and to
* calculate PSNR values for various bitrates.
*/
-public class Vp8EncoderTest extends Vp8CodecTestBase {
+public class VpxEncoderTest extends VpxCodecTestBase {
private static final String ENCODED_IVF_BASE = "football";
private static final String INPUT_YUV = null;
@@ -54,9 +54,9 @@
private static final int[] TEST_BITRATES_SET = { 300000, 500000, 700000, 900000 };
// Maximum allowed bitrate variation from the target value.
private static final double MAX_BITRATE_VARIATION = 0.2;
- // Average PSNR values for reference Google VP8 codec for the above bitrates.
+ // Average PSNR values for reference Google VPx codec for the above bitrates.
private static final double[] REFERENCE_AVERAGE_PSNR = { 33.1, 35.2, 36.6, 37.8 };
- // Minimum PSNR values for reference Google VP8 codec for the above bitrates.
+ // Minimum PSNR values for reference Google VPx codec for the above bitrates.
private static final double[] REFERENCE_MINIMUM_PSNR = { 25.9, 27.5, 28.4, 30.3 };
// Maximum allowed average PSNR difference of encoder comparing to reference Google encoder.
private static final double MAX_AVERAGE_PSNR_DIFFERENCE = 2;
@@ -75,13 +75,13 @@
private static final int MAX_KEYFRAME_INTERVAL_VARIATION = 3;
/**
- * A basic test for VP8 encoder.
+ * A basic test for VPx encoder.
*
* Encodes 9 seconds of raw stream with default configuration options,
* and then decodes it to verify the bitstream.
* Also checks the average bitrate is within MAX_BITRATE_VARIATION of the target value.
*/
- public void testBasic() throws Exception {
+ private void internalTestBasic(String codecMimeType) throws Exception {
int encodeSeconds = 9;
boolean skipped = true;
@@ -89,6 +89,7 @@
EncoderOutputStreamParameters params = getDefaultEncodingParameters(
INPUT_YUV,
ENCODED_IVF_BASE,
+ codecMimeType,
encodeSeconds,
WIDTH,
HEIGHT,
@@ -102,14 +103,14 @@
}
skipped = false;
- Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
+ VpxEncodingStatistics statistics = computeEncodingStatistics(bufInfo);
assertEquals("Stream bitrate " + statistics.mAverageBitrate +
" is different from the target " + targetBitrate,
targetBitrate, statistics.mAverageBitrate,
MAX_BITRATE_VARIATION * targetBitrate);
- decode(params.outputIvfFilename, null, FPS, params.forceGoogleEncoder);
+ decode(params.outputIvfFilename, null, codecMimeType, FPS, params.forceGoogleEncoder);
}
if (skipped) {
@@ -118,13 +119,13 @@
}
/**
- * Asynchronous encoding test for VP8 encoder.
+ * Asynchronous encoding test for VPx encoder.
*
* Encodes 9 seconds of raw stream using synchronous and asynchronous calls.
* Checks the PSNR difference between the encoded and decoded output and reference yuv input
* does not change much for two different ways of the encoder call.
*/
- public void testAsyncEncoding() throws Exception {
+ private void internalTestAsyncEncoding(String codecMimeType) throws Exception {
int encodeSeconds = 9;
// First test the encoder running in a looper thread with buffer callbacks enabled.
@@ -132,6 +133,7 @@
EncoderOutputStreamParameters params = getDefaultEncodingParameters(
INPUT_YUV,
ENCODED_IVF_BASE,
+ codecMimeType,
encodeSeconds,
WIDTH,
HEIGHT,
@@ -145,8 +147,8 @@
return;
}
computeEncodingStatistics(bufInfos);
- decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceGoogleEncoder);
- Vp8DecodingStatistics statisticsAsync = computeDecodingStatistics(
+ decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, params.forceGoogleEncoder);
+ VpxDecodingStatistics statisticsAsync = computeDecodingStatistics(
params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
params.frameWidth, params.frameHeight);
@@ -156,6 +158,7 @@
params = getDefaultEncodingParameters(
INPUT_YUV,
ENCODED_IVF_BASE,
+ codecMimeType,
encodeSeconds,
WIDTH,
HEIGHT,
@@ -169,8 +172,8 @@
return;
}
computeEncodingStatistics(bufInfos);
- decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceGoogleEncoder);
- Vp8DecodingStatistics statisticsSync = computeDecodingStatistics(
+ decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, params.forceGoogleEncoder);
+ VpxDecodingStatistics statisticsSync = computeDecodingStatistics(
params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
params.frameWidth, params.frameHeight);
@@ -193,12 +196,13 @@
* Encodes 9 seconds of raw stream and requests a sync frame every second (30 frames).
* The test does not verify the output stream.
*/
- public void testSyncFrame() throws Exception {
+ private void internalTestSyncFrame(String codecMimeType) throws Exception {
int encodeSeconds = 9;
EncoderOutputStreamParameters params = getDefaultEncodingParameters(
INPUT_YUV,
ENCODED_IVF_BASE,
+ codecMimeType,
encodeSeconds,
WIDTH,
HEIGHT,
@@ -214,7 +218,7 @@
return;
}
- Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
+ VpxEncodingStatistics statistics = computeEncodingStatistics(bufInfo);
// First check if we got expected number of key frames.
int actualKeyFrames = statistics.mKeyFrames.size();
@@ -242,13 +246,14 @@
* Run the the encoder for 12 seconds. Request changes to the
* bitrate after 6 seconds and ensure the encoder responds.
*/
- public void testDynamicBitrateChange() throws Exception {
+ private void internalTestDynamicBitrateChange(String codecMimeType) throws Exception {
int encodeSeconds = 12; // Encoding sequence duration in seconds.
int[] bitrateTargetValues = { 400000, 800000 }; // List of bitrates to test.
EncoderOutputStreamParameters params = getDefaultEncodingParameters(
INPUT_YUV,
ENCODED_IVF_BASE,
+ codecMimeType,
encodeSeconds,
WIDTH,
HEIGHT,
@@ -274,7 +279,7 @@
return;
}
- Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
+ VpxEncodingStatistics statistics = computeEncodingStatistics(bufInfo);
// Calculate actual average bitrates for every [stepSeconds] second.
int[] bitrateActualValues = new int[bitrateTargetValues.length];
@@ -309,11 +314,11 @@
* and then run parallel encoding and decoding of the same streams.
* Compares average bitrate and PSNR for sequential and parallel runs.
*/
- public void testParallelEncodingAndDecoding() throws Exception {
+ private void internalTestParallelEncodingAndDecoding(String codecMimeType) throws Exception {
// check for encoder up front, as by the time we detect lack of
// encoder support, we may have already started decoding.
MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
- MediaFormat format = MediaFormat.createVideoFormat(VP8_MIME, WIDTH, HEIGHT);
+ MediaFormat format = MediaFormat.createVideoFormat(codecMimeType, WIDTH, HEIGHT);
if (mcl.findEncoderForFormat(format) == null) {
Log.i(TAG, "SKIPPING testParallelEncodingAndDecoding(): no suitable encoder found");
return;
@@ -327,6 +332,7 @@
final EncoderOutputStreamParameters params = getDefaultEncodingParameters(
INPUT_YUV,
ENCODED_IVF_BASE,
+ codecMimeType,
encodeSeconds,
WIDTH,
HEIGHT,
@@ -340,7 +346,7 @@
public void run() {
try {
ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
- Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
+ VpxEncodingStatistics statistics = computeEncodingStatistics(bufInfo);
bitrate[0] = statistics.mAverageBitrate;
} catch (Exception e) {
Log.e(TAG, "Encoder error: " + e.toString());
@@ -351,8 +357,8 @@
Runnable runDecoder = new Runnable() {
public void run() {
try {
- decode(inputIvfFilename, OUTPUT_YUV, FPS, params.forceGoogleEncoder);
- Vp8DecodingStatistics statistics = computeDecodingStatistics(
+ decode(inputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, params.forceGoogleEncoder);
+ VpxDecodingStatistics statistics = computeDecodingStatistics(
params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
params.frameWidth, params.frameHeight);
psnr[0] = statistics.mAveragePSNR;
@@ -410,7 +416,7 @@
* Video streams with higher bitrates should have higher PSNRs.
* Also compares average and minimum PSNR of codec with PSNR values of reference Google codec.
*/
- public void testEncoderQuality() throws Exception {
+ private void internalTestEncoderQuality(String codecMimeType) throws Exception {
int encodeSeconds = 9; // Encoding sequence duration in seconds for each bitrate.
double[] psnrPlatformCodecAverage = new double[TEST_BITRATES_SET.length];
double[] psnrPlatformCodecMin = new double[TEST_BITRATES_SET.length];
@@ -423,6 +429,7 @@
EncoderOutputStreamParameters params = getDefaultEncodingParameters(
INPUT_YUV,
ENCODED_IVF_BASE,
+ codecMimeType,
encodeSeconds,
WIDTH,
HEIGHT,
@@ -438,8 +445,8 @@
completed[i] = true;
skipped = false;
- decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceGoogleEncoder);
- Vp8DecodingStatistics statistics = computeDecodingStatistics(
+ decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, params.forceGoogleEncoder);
+ VpxDecodingStatistics statistics = computeDecodingStatistics(
params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
params.frameWidth, params.frameHeight);
psnrPlatformCodecAverage[i] = statistics.mAveragePSNR;
@@ -500,5 +507,32 @@
}
}
}
+
+ public void testBasicVP8() throws Exception { internalTestBasic(VP8_MIME); }
+ public void testBasicVP9() throws Exception { internalTestBasic(VP9_MIME); }
+
+ public void testAsyncEncodingVP8() throws Exception { internalTestAsyncEncoding(VP8_MIME); }
+ public void testAsyncEncodingVP9() throws Exception { internalTestAsyncEncoding(VP9_MIME); }
+
+ public void testSyncFrameVP8() throws Exception { internalTestSyncFrame(VP8_MIME); }
+ public void testSyncFrameVP9() throws Exception { internalTestSyncFrame(VP9_MIME); }
+
+ public void testDynamicBitrateChangeVP8() throws Exception {
+ internalTestDynamicBitrateChange(VP8_MIME);
+ }
+ public void testDynamicBitrateChangeVP9() throws Exception {
+ internalTestDynamicBitrateChange(VP9_MIME);
+ }
+
+ public void testParallelEncodingAndDecodingVP8() throws Exception {
+ internalTestParallelEncodingAndDecoding(VP8_MIME);
+ }
+ public void testParallelEncodingAndDecodingVP9() throws Exception {
+ internalTestParallelEncodingAndDecoding(VP9_MIME);
+ }
+
+ public void testEncoderQualityVP8() throws Exception { internalTestEncoderQuality(VP8_MIME); }
+ public void testEncoderQualityVP9() throws Exception { internalTestEncoderQuality(VP9_MIME); }
+
}
diff --git a/tests/tests/os/Android.mk b/tests/tests/os/Android.mk
index 5397fc6a..abbad8f 100644
--- a/tests/tests/os/Android.mk
+++ b/tests/tests/os/Android.mk
@@ -25,7 +25,7 @@
LOCAL_MULTILIB := both
LOCAL_STATIC_JAVA_LIBRARIES := \
- ctsdeviceutil ctstestrunner guava
+ android-support-test ctsdeviceutil ctstestrunner guava platform-test-annotations
LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libctsos_jni libnativehelper_compat_libc++
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 4ebe527..3d8ab32 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -18,8 +18,8 @@
*/
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android" coreApp="true" android:sharedUserId="android.uid.system"
- android:sharedUserLabel="@string/android_system_label">
+ package="android" coreApp="true" android:sharedUserId="android.uid.system"
+ android:sharedUserLabel="@string/android_system_label">
<!-- ================================================ -->
<!-- Special broadcasts that only the system can send -->
@@ -138,49 +138,46 @@
<protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REPLY" />
<protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL" />
<protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST" />
- <protected-broadcast android:name="android.bluetooth.device.action.SDP_RECORD" />
<protected-broadcast android:name="android.bluetooth.devicepicker.action.LAUNCH" />
<protected-broadcast android:name="android.bluetooth.devicepicker.action.DEVICE_SELECTED" />
<protected-broadcast
- android:name="android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED" />
+ android:name="android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED" />
+ android:name="android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT" />
+ android:name="android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT" />
<protected-broadcast
- android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
+ android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
+ android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.headsetclient.profile.action.AG_EVENT" />
+ android:name="android.bluetooth.headsetclient.profile.action.AG_EVENT" />
<protected-broadcast
- android:name="android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED" />
+ android:name="android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.headsetclient.profile.action.RESULT" />
+ android:name="android.bluetooth.headsetclient.profile.action.RESULT" />
<protected-broadcast
- android:name="android.bluetooth.headsetclient.profile.action.LAST_VTAG" />
+ android:name="android.bluetooth.headsetclient.profile.action.LAST_VTAG" />
<protected-broadcast
- android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
+ android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
+ android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED" />
+ android:name="android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED" />
+ android:name="android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED" />
+ android:name="android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED" />
+ android:name="android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED" />
+ android:name="android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED" />
+ android:name="android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED" />
<protected-broadcast
- android:name="android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS" />
+ android:name="android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS" />
<protected-broadcast
- android:name="android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED" />
- <protected-broadcast
- android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
+ android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast android:name="android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED" />
<protected-broadcast android:name="android.btopp.intent.action.INCOMING_FILE_NOTIFICATION" />
<protected-broadcast android:name="android.btopp.intent.action.USER_CONFIRMATION_TIMEOUT" />
@@ -192,7 +189,6 @@
<protected-broadcast android:name="android.btopp.intent.action.RETRY" />
<protected-broadcast android:name="android.btopp.intent.action.OPEN" />
<protected-broadcast android:name="android.btopp.intent.action.OPEN_INBOUND" />
- <protected-broadcast android:name="android.btopp.intent.action.TRANSFER_COMPLETE" />
<protected-broadcast android:name="com.android.bluetooth.pbap.authchall" />
<protected-broadcast android:name="com.android.bluetooth.pbap.userconfirmtimeout" />
<protected-broadcast android:name="com.android.bluetooth.pbap.authresponse" />
@@ -310,7 +306,7 @@
<protected-broadcast android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_START" />
<protected-broadcast android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_END" />
- <protected-broadcast android:name="com.android.server.ACTION_TRIGGER_IDLE" />
+ <protected-broadcast android:name="com.android.server.task.controllers.IdleController.ACTION_TRIGGER_IDLE" />
<protected-broadcast android:name="android.intent.action.HDMI_PLUGGED" />
@@ -330,11 +326,11 @@
<protected-broadcast android:name="android.provider.Telephony.MMS_DOWNLOADED" />
<protected-broadcast
- android:name="com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION" />
+ android:name="com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION" />
<!-- Defined in RestrictionsManager -->
<protected-broadcast
- android:name="android.intent.action.PERMISSION_RESPONSE_RECEIVED" />
+ android:name="android.intent.action.PERMISSION_RESPONSE_RECEIVED" />
<!-- Defined in RestrictionsManager -->
<protected-broadcast android:name="android.intent.action.REQUEST_PERMISSION" />
@@ -496,28 +492,28 @@
<!-- Used for runtime permissions related to contacts and profiles on this
device. -->
<permission-group android:name="android.permission-group.CONTACTS"
- android:icon="@drawable/perm_group_contacts"
- android:label="@string/permgrouplab_contacts"
- android:description="@string/permgroupdesc_contacts"
- android:priority="100" />
+ android:icon="@drawable/perm_group_contacts"
+ android:label="@string/permgrouplab_contacts"
+ android:description="@string/permgroupdesc_contacts"
+ android:priority="100" />
<!-- Allows an application to read the user's contacts data.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_CONTACTS"
- android:permissionGroup="android.permission-group.CONTACTS"
- android:label="@string/permlab_readContacts"
- android:description="@string/permdesc_readContacts"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.CONTACTS"
+ android:label="@string/permlab_readContacts"
+ android:description="@string/permdesc_readContacts"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to write the user's contacts data.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.WRITE_CONTACTS"
- android:permissionGroup="android.permission-group.CONTACTS"
- android:label="@string/permlab_writeContacts"
- android:description="@string/permdesc_writeContacts"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.CONTACTS"
+ android:label="@string/permlab_writeContacts"
+ android:description="@string/permdesc_writeContacts"
+ android:protectionLevel="dangerous" />
<!-- ====================================================================== -->
<!-- Permissions for accessing user's calendar -->
@@ -526,28 +522,28 @@
<!-- Used for runtime permissions related to user's calendar. -->
<permission-group android:name="android.permission-group.CALENDAR"
- android:icon="@drawable/perm_group_calendar"
- android:label="@string/permgrouplab_calendar"
- android:description="@string/permgroupdesc_calendar"
- android:priority="200" />
+ android:icon="@drawable/perm_group_calendar"
+ android:label="@string/permgrouplab_calendar"
+ android:description="@string/permgroupdesc_calendar"
+ android:priority="200" />
<!-- Allows an application to read the user's calendar data.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_CALENDAR"
- android:permissionGroup="android.permission-group.CALENDAR"
- android:label="@string/permlab_readCalendar"
- android:description="@string/permdesc_readCalendar"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.CALENDAR"
+ android:label="@string/permlab_readCalendar"
+ android:description="@string/permdesc_readCalendar"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to write the user's calendar data.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.WRITE_CALENDAR"
- android:permissionGroup="android.permission-group.CALENDAR"
- android:label="@string/permlab_writeCalendar"
- android:description="@string/permdesc_writeCalendar"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.CALENDAR"
+ android:label="@string/permlab_writeCalendar"
+ android:description="@string/permdesc_writeCalendar"
+ android:protectionLevel="dangerous" />
<!-- ====================================================================== -->
<!-- Permissions for accessing and modifying user's SMS messages -->
@@ -556,56 +552,56 @@
<!-- Used for runtime permissions related to user's SMS messages. -->
<permission-group android:name="android.permission-group.SMS"
- android:icon="@drawable/perm_group_sms"
- android:label="@string/permgrouplab_sms"
- android:description="@string/permgroupdesc_sms"
- android:priority="300" />
+ android:icon="@drawable/perm_group_sms"
+ android:label="@string/permgrouplab_sms"
+ android:description="@string/permgroupdesc_sms"
+ android:priority="300" />
<!-- Allows an application to send SMS messages.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.SEND_SMS"
- android:permissionGroup="android.permission-group.SMS"
- android:label="@string/permlab_sendSms"
- android:description="@string/permdesc_sendSms"
- android:permissionFlags="costsMoney"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.SMS"
+ android:label="@string/permlab_sendSms"
+ android:description="@string/permdesc_sendSms"
+ android:permissionFlags="costsMoney"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to receive SMS messages.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.RECEIVE_SMS"
- android:permissionGroup="android.permission-group.SMS"
- android:label="@string/permlab_receiveSms"
- android:description="@string/permdesc_receiveSms"
- android:protectionLevel="dangerous"/>
+ android:permissionGroup="android.permission-group.SMS"
+ android:label="@string/permlab_receiveSms"
+ android:description="@string/permdesc_receiveSms"
+ android:protectionLevel="dangerous"/>
<!-- Allows an application to read SMS messages.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_SMS"
- android:permissionGroup="android.permission-group.SMS"
- android:label="@string/permlab_readSms"
- android:description="@string/permdesc_readSms"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.SMS"
+ android:label="@string/permlab_readSms"
+ android:description="@string/permdesc_readSms"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to receive WAP push messages.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.RECEIVE_WAP_PUSH"
- android:permissionGroup="android.permission-group.SMS"
- android:label="@string/permlab_receiveWapPush"
- android:description="@string/permdesc_receiveWapPush"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.SMS"
+ android:label="@string/permlab_receiveWapPush"
+ android:description="@string/permdesc_receiveWapPush"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to monitor incoming MMS messages.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.RECEIVE_MMS"
- android:permissionGroup="android.permission-group.SMS"
- android:label="@string/permlab_receiveMms"
- android:description="@string/permdesc_receiveMms"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.SMS"
+ android:label="@string/permlab_receiveMms"
+ android:description="@string/permdesc_receiveMms"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to read previously received cell broadcast
messages and to register a content observer to get notifications when
@@ -620,10 +616,10 @@
<p>Protection level: dangerous
@hide Pending API council approval -->
<permission android:name="android.permission.READ_CELL_BROADCASTS"
- android:permissionGroup="android.permission-group.SMS"
- android:label="@string/permlab_readCellBroadcasts"
- android:description="@string/permdesc_readCellBroadcasts"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.SMS"
+ android:label="@string/permlab_readCellBroadcasts"
+ android:description="@string/permdesc_readCellBroadcasts"
+ android:protectionLevel="dangerous" />
<!-- ====================================================================== -->
<!-- Permissions for accessing external storage -->
@@ -632,10 +628,10 @@
<!-- Used for runtime permissions related to the shared external storage. -->
<permission-group android:name="android.permission-group.STORAGE"
- android:icon="@drawable/perm_group_storage"
- android:label="@string/permgrouplab_storage"
- android:description="@string/permgroupdesc_storage"
- android:priority="900" />
+ android:icon="@drawable/perm_group_storage"
+ android:label="@string/permgrouplab_storage"
+ android:description="@string/permgroupdesc_storage"
+ android:priority="900" />
<!-- Allows an application to read from external storage.
<p>Any app that declares the {@link #WRITE_EXTERNAL_STORAGE} permission is implicitly
@@ -660,10 +656,10 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_EXTERNAL_STORAGE"
- android:permissionGroup="android.permission-group.STORAGE"
- android:label="@string/permlab_sdcardRead"
- android:description="@string/permdesc_sdcardRead"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.STORAGE"
+ android:label="@string/permlab_sdcardRead"
+ android:description="@string/permdesc_sdcardRead"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to write to external storage.
<p class="note"><strong>Note:</strong> If <em>both</em> your <a
@@ -681,10 +677,10 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
- android:permissionGroup="android.permission-group.STORAGE"
- android:label="@string/permlab_sdcardWrite"
- android:description="@string/permdesc_sdcardWrite"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.STORAGE"
+ android:label="@string/permlab_sdcardWrite"
+ android:description="@string/permdesc_sdcardWrite"
+ android:protectionLevel="dangerous" />
<!-- ====================================================================== -->
<!-- Permissions for accessing the device location -->
@@ -693,28 +689,28 @@
<!-- Used for permissions that allow accessing the device location. -->
<permission-group android:name="android.permission-group.LOCATION"
- android:icon="@drawable/perm_group_location"
- android:label="@string/permgrouplab_location"
- android:description="@string/permgroupdesc_location"
- android:priority="400" />
+ android:icon="@drawable/perm_group_location"
+ android:label="@string/permgrouplab_location"
+ android:description="@string/permgroupdesc_location"
+ android:priority="400" />
<!-- Allows an app to access precise location.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.ACCESS_FINE_LOCATION"
- android:permissionGroup="android.permission-group.LOCATION"
- android:label="@string/permlab_accessFineLocation"
- android:description="@string/permdesc_accessFineLocation"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.LOCATION"
+ android:label="@string/permlab_accessFineLocation"
+ android:description="@string/permdesc_accessFineLocation"
+ android:protectionLevel="dangerous" />
<!-- Allows an app to access approximate location.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.ACCESS_COARSE_LOCATION"
- android:permissionGroup="android.permission-group.LOCATION"
- android:label="@string/permlab_accessCoarseLocation"
- android:description="@string/permdesc_accessCoarseLocation"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.LOCATION"
+ android:label="@string/permlab_accessCoarseLocation"
+ android:description="@string/permdesc_accessCoarseLocation"
+ android:protectionLevel="dangerous" />
<!-- ====================================================================== -->
<!-- Permissions for accessing the device telephony -->
@@ -723,10 +719,10 @@
<!-- Used for permissions that are associated telephony features. -->
<permission-group android:name="android.permission-group.PHONE"
- android:icon="@drawable/perm_group_phone_calls"
- android:label="@string/permgrouplab_phone"
- android:description="@string/permgroupdesc_phone"
- android:priority="500" />
+ android:icon="@drawable/perm_group_phone_calls"
+ android:label="@string/permgrouplab_phone"
+ android:description="@string/permgroupdesc_phone"
+ android:priority="500" />
<!-- Allows read only access to phone state, including the phone number of the device,
current cellular network information, the status of any ongoing calls, and a list of any
@@ -742,21 +738,21 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_PHONE_STATE"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_readPhoneState"
- android:description="@string/permdesc_readPhoneState"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.PHONE"
+ android:label="@string/permlab_readPhoneState"
+ android:description="@string/permdesc_readPhoneState"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to initiate a phone call without going through
the Dialer user interface for the user to confirm the call.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.CALL_PHONE"
- android:permissionGroup="android.permission-group.PHONE"
- android:permissionFlags="costsMoney"
- android:label="@string/permlab_callPhone"
- android:description="@string/permdesc_callPhone"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.PHONE"
+ android:permissionFlags="costsMoney"
+ android:label="@string/permlab_callPhone"
+ android:description="@string/permdesc_callPhone"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to access the IMS call service: making and
modifying a call
@@ -764,10 +760,10 @@
@hide
-->
<permission android:name="android.permission.ACCESS_IMS_CALL_SERVICE"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_accessImsCallService"
- android:description="@string/permdesc_accessImsCallService"
- android:protectionLevel="signature|privileged" />
+ android:permissionGroup="android.permission-group.PHONE"
+ android:label="@string/permlab_accessImsCallService"
+ android:description="@string/permdesc_accessImsCallService"
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to read the user's call log.
<p class="note"><strong>Note:</strong> If your app uses the
@@ -782,10 +778,10 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_CALL_LOG"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_readCallLog"
- android:description="@string/permdesc_readCallLog"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.PHONE"
+ android:label="@string/permlab_readCallLog"
+ android:description="@string/permdesc_readCallLog"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to write (but not read) the user's
call log data.
@@ -801,28 +797,28 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.WRITE_CALL_LOG"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_writeCallLog"
- android:description="@string/permdesc_writeCallLog"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.PHONE"
+ android:label="@string/permlab_writeCallLog"
+ android:description="@string/permdesc_writeCallLog"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to add voicemails into the system.
<p>Protection level: dangerous
-->
<permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_addVoicemail"
- android:description="@string/permdesc_addVoicemail"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.PHONE"
+ android:label="@string/permlab_addVoicemail"
+ android:description="@string/permdesc_addVoicemail"
+ android:protectionLevel="dangerous" />
<!-- Allows an application to use SIP service.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.USE_SIP"
- android:permissionGroup="android.permission-group.PHONE"
- android:description="@string/permdesc_use_sip"
- android:label="@string/permlab_use_sip"
- android:protectionLevel="dangerous"/>
+ android:permissionGroup="android.permission-group.PHONE"
+ android:description="@string/permdesc_use_sip"
+ android:label="@string/permlab_use_sip"
+ android:protectionLevel="dangerous"/>
<!-- Allows an application to see the number being dialed during an outgoing
call with the option to redirect the call to a different number or
@@ -830,10 +826,10 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.PROCESS_OUTGOING_CALLS"
- android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_processOutgoingCalls"
- android:description="@string/permdesc_processOutgoingCalls"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.PHONE"
+ android:label="@string/permlab_processOutgoingCalls"
+ android:description="@string/permdesc_processOutgoingCalls"
+ android:protectionLevel="dangerous" />
<!-- ====================================================================== -->
<!-- Permissions for accessing the device microphone -->
@@ -844,19 +840,19 @@
microphone audio from the device. Note that phone calls also capture audio
but are in a separate (more visible) permission group. -->
<permission-group android:name="android.permission-group.MICROPHONE"
- android:icon="@drawable/perm_group_microphone"
- android:label="@string/permgrouplab_microphone"
- android:description="@string/permgroupdesc_microphone"
- android:priority="600" />
+ android:icon="@drawable/perm_group_microphone"
+ android:label="@string/permgrouplab_microphone"
+ android:description="@string/permgroupdesc_microphone"
+ android:priority="600" />
<!-- Allows an application to record audio.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.RECORD_AUDIO"
- android:permissionGroup="android.permission-group.MICROPHONE"
- android:label="@string/permlab_recordAudio"
- android:description="@string/permdesc_recordAudio"
- android:protectionLevel="dangerous"/>
+ android:permissionGroup="android.permission-group.MICROPHONE"
+ android:label="@string/permlab_recordAudio"
+ android:description="@string/permdesc_recordAudio"
+ android:protectionLevel="dangerous"/>
<!-- ====================================================================== -->
<!-- Permissions for accessing the UCE Service -->
@@ -866,15 +862,15 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.ACCESS_UCE_PRESENCE_SERVICE"
- android:permissionGroup="android.permission-group.PHONE"
- android:protectionLevel="signatureOrSystem"/>
+ android:permissionGroup="android.permission-group.PHONE"
+ android:protectionLevel="signatureOrSystem"/>
<!-- @hide Allows an application to Access UCE-OPTIONS.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.ACCESS_UCE_OPTIONS_SERVICE"
- android:permissionGroup="android.permission-group.PHONE"
- android:protectionLevel="signatureOrSystem"/>
+ android:permissionGroup="android.permission-group.PHONE"
+ android:protectionLevel="signatureOrSystem"/>
@@ -886,10 +882,10 @@
<!-- Used for permissions that are associated with accessing
camera or capturing images/video from the device. -->
<permission-group android:name="android.permission-group.CAMERA"
- android:icon="@drawable/perm_group_camera"
- android:label="@string/permgrouplab_camera"
- android:description="@string/permgroupdesc_camera"
- android:priority="700" />
+ android:icon="@drawable/perm_group_camera"
+ android:label="@string/permgrouplab_camera"
+ android:description="@string/permgroupdesc_camera"
+ android:priority="700" />
<!-- Required to be able to access the camera device.
<p>This will automatically enforce the <a
@@ -901,10 +897,10 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.CAMERA"
- android:permissionGroup="android.permission-group.CAMERA"
- android:label="@string/permlab_camera"
- android:description="@string/permdesc_camera"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.CAMERA"
+ android:label="@string/permlab_camera"
+ android:description="@string/permdesc_camera"
+ android:protectionLevel="dangerous" />
<!-- ====================================================================== -->
@@ -915,28 +911,28 @@
<!-- Used for permissions that are associated with accessing
camera or capturing images/video from the device. -->
<permission-group android:name="android.permission-group.SENSORS"
- android:icon="@drawable/perm_group_sensors"
- android:label="@string/permgrouplab_sensors"
- android:description="@string/permgroupdesc_sensors"
- android:priority="800" />
+ android:icon="@drawable/perm_group_sensors"
+ android:label="@string/permgrouplab_sensors"
+ android:description="@string/permgroupdesc_sensors"
+ android:priority="800" />
<!-- Allows an application to access data from sensors that the user uses to
measure what is happening inside his/her body, such as heart rate.
<p>Protection level: dangerous -->
<permission android:name="android.permission.BODY_SENSORS"
- android:permissionGroup="android.permission-group.SENSORS"
- android:label="@string/permlab_bodySensors"
- android:description="@string/permdesc_bodySensors"
- android:protectionLevel="dangerous" />
+ android:permissionGroup="android.permission-group.SENSORS"
+ android:label="@string/permlab_bodySensors"
+ android:description="@string/permdesc_bodySensors"
+ android:protectionLevel="dangerous" />
<!-- Allows an app to use fingerprint hardware.
<p>Protection level: normal
-->
<permission android:name="android.permission.USE_FINGERPRINT"
- android:permissionGroup="android.permission-group.SENSORS"
- android:label="@string/permlab_useFingerprint"
- android:description="@string/permdesc_useFingerprint"
- android:protectionLevel="normal" />
+ android:permissionGroup="android.permission-group.SENSORS"
+ android:label="@string/permlab_useFingerprint"
+ android:description="@string/permdesc_useFingerprint"
+ android:protectionLevel="normal" />
<!-- ====================================================================== -->
<!-- REMOVED PERMISSIONS -->
@@ -944,78 +940,78 @@
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.READ_PROFILE"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.WRITE_PROFILE"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.READ_SOCIAL_STREAM"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.WRITE_SOCIAL_STREAM"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.READ_USER_DICTIONARY"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.WRITE_USER_DICTIONARY"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.WRITE_SMS"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.MANAGE_ACCOUNTS"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.USE_CREDENTIALS"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.SUBSCRIBED_FEEDS_READ"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.SUBSCRIBED_FEEDS_WRITE"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- @hide We need to keep this around for backwards compatibility -->
<permission android:name="android.permission.FLASHLIGHT"
- android:protectionLevel="normal"
- android:permissionFlags="removed"/>
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
<!-- ====================================================================== -->
<!-- INSTALL PERMISSIONS -->
@@ -1030,37 +1026,35 @@
to handle the respond-via-message action during incoming calls.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.SEND_RESPOND_VIA_MESSAGE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to send SMS to premium shortcodes without user permission.
- <p>Not for use by third-party applications.
- @hide -->
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.SEND_SMS_NO_CONFIRMATION"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to filter carrier specific sms.
@hide -->
<permission android:name="android.permission.CARRIER_FILTER_SMS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to receive emergency cell broadcast messages,
to record or display them to the user.
- <p>Not for use by third-party applications.
- @hide -->
+ <p>Not for use by third-party applications. -->
<permission android:name="android.permission.RECEIVE_EMERGENCY_BROADCAST"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to monitor incoming Bluetooth MAP messages, to record
or perform processing on them. -->
<!-- @hide -->
<permission android:name="android.permission.RECEIVE_BLUETOOTH_MAP"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows an application to execute contacts directory search.
This should only be used by ContactsProvider.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.BIND_DIRECTORY_SEARCH"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows an application to modify cell broadcasts through the content provider.
<p>Not for use by third-party applications. -->
@@ -1076,9 +1070,9 @@
<p>Protection level: normal
-->
<permission android:name="com.android.alarm.permission.SET_ALARM"
- android:label="@string/permlab_setAlarm"
- android:description="@string/permdesc_setAlarm"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_setAlarm"
+ android:description="@string/permdesc_setAlarm"
+ android:protectionLevel="normal" />
<!-- =============================================================== -->
<!-- Permissions for accessing the user voicemail -->
@@ -1089,13 +1083,13 @@
<p>Protection level: signature|privileged
-->
<permission android:name="com.android.voicemail.permission.WRITE_VOICEMAIL"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to read voicemails in the system.
<p>Protection level: signature|privileged
-->
<permission android:name="com.android.voicemail.permission.READ_VOICEMAIL"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- ======================================= -->
<!-- Permissions for accessing location info -->
@@ -1106,26 +1100,26 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"
- android:label="@string/permlab_accessLocationExtraCommands"
- android:description="@string/permdesc_accessLocationExtraCommands"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_accessLocationExtraCommands"
+ android:description="@string/permdesc_accessLocationExtraCommands"
+ android:protectionLevel="normal" />
<!-- @SystemApi Allows an application to install a location provider into the Location Manager.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.INSTALL_LOCATION_PROVIDER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows HDMI-CEC service to access device and configuration files.
This should only be used by HDMI-CEC service.
-->
<permission android:name="android.permission.HDMI_CEC"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to use location features in hardware,
such as the geofencing api.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.LOCATION_HARDWARE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<uses-permission android:name="android.permission.LOCATION_HARDWARE"/>
<!-- @SystemApi Allows an application to create mock location providers for testing.
@@ -1133,7 +1127,7 @@
@hide
-->
<permission android:name="android.permission.ACCESS_MOCK_LOCATION"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- ======================================= -->
<!-- Permissions for accessing networks -->
@@ -1144,73 +1138,73 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.INTERNET"
- android:description="@string/permdesc_createNetworkSockets"
- android:label="@string/permlab_createNetworkSockets"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_createNetworkSockets"
+ android:label="@string/permlab_createNetworkSockets"
+ android:protectionLevel="normal" />
<!-- Allows applications to access information about networks.
<p>Protection level: normal
-->
<permission android:name="android.permission.ACCESS_NETWORK_STATE"
- android:description="@string/permdesc_accessNetworkState"
- android:label="@string/permlab_accessNetworkState"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_accessNetworkState"
+ android:label="@string/permlab_accessNetworkState"
+ android:protectionLevel="normal" />
<!-- Allows applications to access information about Wi-Fi networks.
<p>Protection level: normal
-->
<permission android:name="android.permission.ACCESS_WIFI_STATE"
- android:description="@string/permdesc_accessWifiState"
- android:label="@string/permlab_accessWifiState"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_accessWifiState"
+ android:label="@string/permlab_accessWifiState"
+ android:protectionLevel="normal" />
<!-- Allows applications to change Wi-Fi connectivity state.
<p>Protection level: normal
-->
<permission android:name="android.permission.CHANGE_WIFI_STATE"
- android:description="@string/permdesc_changeWifiState"
- android:label="@string/permlab_changeWifiState"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_changeWifiState"
+ android:label="@string/permlab_changeWifiState"
+ android:protectionLevel="normal" />
<!-- @SystemApi @hide Allows applications to read Wi-Fi credential.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.READ_WIFI_CREDENTIAL"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows applications to change tether state and run
tether carrier provisioning.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.TETHER_PRIVILEGED"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allow system apps to receive broadcast
when a wifi network credential is changed.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows an application to modify any wifi configuration, even if created
by another application. Once reconfigured the original creator cannot make any further
modifications.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.OVERRIDE_WIFI_CONFIG"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @hide -->
<permission android:name="android.permission.ACCESS_WIMAX_STATE"
- android:description="@string/permdesc_accessWimaxState"
- android:label="@string/permlab_accessWimaxState"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_accessWimaxState"
+ android:label="@string/permlab_accessWimaxState"
+ android:protectionLevel="normal" />
<!-- @hide -->
<permission android:name="android.permission.CHANGE_WIMAX_STATE"
- android:description="@string/permdesc_changeWimaxState"
- android:label="@string/permlab_changeWimaxState"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_changeWimaxState"
+ android:label="@string/permlab_changeWimaxState"
+ android:protectionLevel="normal" />
<!-- Allows applications to act as network scorers. @hide @SystemApi-->
<permission android:name="android.permission.SCORE_NETWORKS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- ======================================= -->
<!-- Permissions for short range, peripheral networks -->
@@ -1221,68 +1215,68 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.BLUETOOTH"
- android:description="@string/permdesc_bluetooth"
- android:label="@string/permlab_bluetooth"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_bluetooth"
+ android:label="@string/permlab_bluetooth"
+ android:protectionLevel="normal" />
<!-- Allows applications to discover and pair bluetooth devices.
<p>Protection level: normal
-->
<permission android:name="android.permission.BLUETOOTH_ADMIN"
- android:description="@string/permdesc_bluetoothAdmin"
- android:label="@string/permlab_bluetoothAdmin"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_bluetoothAdmin"
+ android:label="@string/permlab_bluetoothAdmin"
+ android:protectionLevel="normal" />
<!-- @SystemApi Allows applications to pair bluetooth devices without user interaction, and to
allow or disallow phonebook access or message access.
This is not available to third party applications. -->
<permission android:name="android.permission.BLUETOOTH_PRIVILEGED"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Control access to email providers exclusively for Bluetooth
@hide
-->
<permission android:name="android.permission.BLUETOOTH_MAP"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows bluetooth stack to access files
@hide This should only be used by Bluetooth apk.
-->
<permission android:name="android.permission.BLUETOOTH_STACK"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows applications to perform I/O operations over NFC.
<p>Protection level: normal
-->
<permission android:name="android.permission.NFC"
- android:description="@string/permdesc_nfc"
- android:label="@string/permlab_nfc"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_nfc"
+ android:label="@string/permlab_nfc"
+ android:protectionLevel="normal" />
<!-- @SystemApi Allows an internal user to use privileged ConnectivityManager APIs.
@hide -->
<permission android:name="android.permission.CONNECTIVITY_INTERNAL"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows a system application to access hardware packet offload capabilities.
@hide -->
<permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi
@hide -->
<permission android:name="android.permission.RECEIVE_DATA_ACTIVITY_CHANGE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows access to the loop radio (Android@Home mesh network) device.
@hide -->
<permission android:name="android.permission.LOOP_RADIO"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows sending and receiving handover transfer status from Wifi and Bluetooth
@hide -->
<permission android:name="android.permission.NFC_HANDOVER_STATUS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- ================================== -->
<!-- Permissions for accessing accounts -->
@@ -1301,15 +1295,15 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.GET_ACCOUNTS"
- android:permissionGroup="android.permission-group.CONTACTS"
- android:protectionLevel="dangerous"
- android:description="@string/permdesc_getAccounts"
- android:label="@string/permlab_getAccounts" />
+ android:permissionGroup="android.permission-group.CONTACTS"
+ android:protectionLevel="dangerous"
+ android:description="@string/permdesc_getAccounts"
+ android:label="@string/permlab_getAccounts" />
<!-- @SystemApi Allows applications to call into AccountAuthenticators.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.ACCOUNT_MANAGER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- ================================== -->
<!-- Permissions for accessing hardware that may effect battery life-->
@@ -1320,34 +1314,34 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"
- android:description="@string/permdesc_changeWifiMulticastState"
- android:label="@string/permlab_changeWifiMulticastState"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_changeWifiMulticastState"
+ android:label="@string/permlab_changeWifiMulticastState"
+ android:protectionLevel="normal" />
<!-- Allows access to the vibrator.
<p>Protection level: normal
-->
<permission android:name="android.permission.VIBRATE"
- android:label="@string/permlab_vibrate"
- android:description="@string/permdesc_vibrate"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_vibrate"
+ android:description="@string/permdesc_vibrate"
+ android:protectionLevel="normal" />
<!-- Allows using PowerManager WakeLocks to keep processor from sleeping or screen
from dimming.
<p>Protection level: normal
-->
<permission android:name="android.permission.WAKE_LOCK"
- android:label="@string/permlab_wakeLock"
- android:description="@string/permdesc_wakeLock"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_wakeLock"
+ android:description="@string/permdesc_wakeLock"
+ android:protectionLevel="normal" />
<!-- Allows using the device's IR transmitter, if available.
<p>Protection level: normal
-->
<permission android:name="android.permission.TRANSMIT_IR"
- android:label="@string/permlab_transmitIr"
- android:description="@string/permdesc_transmitIr"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_transmitIr"
+ android:description="@string/permdesc_transmitIr"
+ android:protectionLevel="normal" />
<!-- ==================================================== -->
<!-- Permissions related to changing audio settings -->
@@ -1358,9 +1352,9 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"
- android:label="@string/permlab_modifyAudioSettings"
- android:description="@string/permdesc_modifyAudioSettings"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_modifyAudioSettings"
+ android:description="@string/permdesc_modifyAudioSettings"
+ android:protectionLevel="normal" />
<!-- ================================== -->
<!-- Permissions for accessing hardware -->
@@ -1370,53 +1364,53 @@
<!-- @SystemApi Allows an application to manage preferences and permissions for USB devices
@hide -->
<permission android:name="android.permission.MANAGE_USB"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to access the MTP USB kernel driver.
For use only by the device side MTP implementation.
@hide -->
<permission android:name="android.permission.ACCESS_MTP"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows access to hardware peripherals. Intended only for hardware testing.
<p>Not for use by third-party applications.
@hide
-->
<permission android:name="android.permission.HARDWARE_TEST"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows access to FM
@hide This is not a third-party API (intended for system apps).-->
<permission android:name="android.permission.ACCESS_FM_RADIO"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows access to configure network interfaces, configure/use IPSec, etc.
@hide -->
<permission android:name="android.permission.NET_ADMIN"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows registration for remote audio playback. @hide -->
<permission android:name="android.permission.REMOTE_AUDIO_PLAYBACK"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows TvInputService to access underlying TV input hardware such as
built-in tuners and HDMI-in's.
@hide This should only be used by OEM's TvInputService's.
-->
<permission android:name="android.permission.TV_INPUT_HARDWARE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows to capture a frame of TV input hardware such as
built-in tuners and HDMI-in's.
@hide <p>Not for use by third-party applications.
-->
<permission android:name="android.permission.CAPTURE_TV_INPUT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @hide Allows TvInputService to access DVB device.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.DVB_DEVICE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows reading the OEM unlock state
@hide <p>Not for use by third-party applications. -->
@@ -1426,17 +1420,17 @@
<!-- @hide Allows enabling/disabling OEM unlock
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.OEM_UNLOCK_STATE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows querying state of PersistentDataBlock
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.ACCESS_PDB_STATE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows system update service to notify device owner about pending updates.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.NOTIFY_PENDING_SYSTEM_UPDATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- =========================================== -->
<!-- Permissions associated with camera and image capture -->
@@ -1447,12 +1441,12 @@
a camera is in use by an application.
@hide -->
<permission android:name="android.permission.CAMERA_DISABLE_TRANSMIT_LED"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows sending the camera service notifications about system-wide events.
@hide -->
<permission android:name="android.permission.CAMERA_SEND_SYSTEM_EVENTS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- =========================================== -->
<!-- Permissions associated with telephony state -->
@@ -1463,50 +1457,50 @@
Does not include placing calls.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.MODIFY_PHONE_STATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows read only access to precise phone state.
@hide Pending API council approval -->
<permission android:name="android.permission.READ_PRECISE_PHONE_STATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows read access to privileged phone state.
@hide Used internally. -->
<permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Protects the ability to register any PhoneAccount with
PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION. This capability indicates that the PhoneAccount
corresponds to a device SIM.
@hide -->
<permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Protects the ability to register any PhoneAccount with
PhoneAccount#CAPABILITY_CALL_PROVIDER.
@hide -->
<permission android:name="android.permission.REGISTER_CALL_PROVIDER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Protects the ability to register any PhoneAccount with
PhoneAccount#CAPABILITY_CONNECTION_MANAGER
@hide -->
<permission android:name="android.permission.REGISTER_CONNECTION_MANAGER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by a {@link android.telecom.InCallService},
to ensure that only the system can bind to it.
<p>Protection level: signature|privileged
-->
<permission android:name="android.permission.BIND_INCALL_SERVICE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by a {@link android.telecom.CallScreeningService},
to ensure that only the system can bind to it.
<p>Protection level: signature|privileged
-->
<permission android:name="android.permission.BIND_SCREENING_SERVICE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by a {@link android.telecom.ConnectionService},
to ensure that only the system can bind to it.
@@ -1515,24 +1509,24 @@
@SystemApi
@hide -->
<permission android:name="android.permission.BIND_CONNECTION_SERVICE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by a {@link android.telecom.ConnectionService},
to ensure that only the system can bind to it.
<p>Protection level: signature|privileged
-->
<permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to control the in-call experience.
@hide -->
<permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to receive STK related commands.
@hide -->
<permission android:name="android.permission.RECEIVE_STK_COMMANDS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- ================================== -->
<!-- Permissions for sdcard interaction -->
@@ -1542,7 +1536,7 @@
<!-- @SystemApi Allows an application to write to internal media storage
@hide -->
<permission android:name="android.permission.WRITE_MEDIA_STORAGE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to manage access to documents, usually as part
of a document picker.
@@ -1552,14 +1546,14 @@
<p>Protection level: signature
-->
<permission android:name="android.permission.MANAGE_DOCUMENTS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows an application to cache content.
<p>Not for use by third-party applications.
<p>Protection level: signature
-->
<permission android:name="android.permission.CACHE_CONTENT"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- ================================== -->
<!-- Permissions for screenlock -->
@@ -1570,9 +1564,9 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.DISABLE_KEYGUARD"
- android:description="@string/permdesc_disableKeyguard"
- android:label="@string/permlab_disableKeyguard"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_disableKeyguard"
+ android:label="@string/permlab_disableKeyguard"
+ android:protectionLevel="normal" />
<!-- ================================== -->
<!-- Permissions to access other installed applications -->
@@ -1581,9 +1575,9 @@
<!-- @deprecated No longer enforced. -->
<permission android:name="android.permission.GET_TASKS"
- android:label="@string/permlab_getTasks"
- android:description="@string/permdesc_getTasks"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_getTasks"
+ android:description="@string/permdesc_getTasks"
+ android:protectionLevel="normal" />
<!-- New version of GET_TASKS that apps can request, since GET_TASKS doesn't really
give access to task information. We need this new one because there are
@@ -1596,32 +1590,32 @@
@hide
@SystemApi -->
<permission android:name="android.permission.REAL_GET_TASKS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to start a task from a ActivityManager#RecentTaskInfo.
@hide -->
<permission android:name="android.permission.START_TASKS_FROM_RECENTS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows an application to call APIs that allow it to do interactions
across the users on the device, using singleton services and
user-targeted broadcasts. This permission is not available to
third party applications. -->
<permission android:name="android.permission.INTERACT_ACROSS_USERS"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Fuller form of {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
that removes restrictions on where broadcasts can be sent and allows other
types of interactions
@hide -->
<permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
- android:protectionLevel="signature|installer" />
+ android:protectionLevel="signature|installer" />
<!-- @SystemApi @hide Allows an application to call APIs that allow it to query and manage
users on the device. This permission is not available to
third party applications. -->
<permission android:name="android.permission.MANAGE_USERS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @hide Allows an application to create, remove users and get the list of
users on the device. Applications holding this permission can only create restricted,
@@ -1634,69 +1628,69 @@
<!-- @hide Allows an application to set the profile owners and the device owner.
This permission is not available to third party applications.-->
<permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"
- android:protectionLevel="signature"
- android:label="@string/permlab_manageProfileAndDeviceOwners"
- android:description="@string/permdesc_manageProfileAndDeviceOwners" />
+ android:protectionLevel="signature"
+ android:label="@string/permlab_manageProfileAndDeviceOwners"
+ android:description="@string/permdesc_manageProfileAndDeviceOwners" />
<!-- Allows an application to get full detailed information about
recently running tasks, with full fidelity to the real state.
@hide -->
<permission android:name="android.permission.GET_DETAILED_TASKS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to change the Z-order of tasks.
<p>Protection level: normal
-->
<permission android:name="android.permission.REORDER_TASKS"
- android:label="@string/permlab_reorderTasks"
- android:description="@string/permdesc_reorderTasks"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_reorderTasks"
+ android:description="@string/permdesc_reorderTasks"
+ android:protectionLevel="normal" />
<!-- @hide Allows an application to change to remove/kill tasks -->
<permission android:name="android.permission.REMOVE_TASKS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi @hide Allows an application to create/manage/remove stacks -->
<permission android:name="android.permission.MANAGE_ACTIVITY_STACKS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to start any activity, regardless of permission
protection or exported state.
@hide -->
<permission android:name="android.permission.START_ANY_ACTIVITY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @deprecated The {@link android.app.ActivityManager#restartPackage}
API is no longer supported. -->
<permission android:name="android.permission.RESTART_PACKAGES"
- android:label="@string/permlab_killBackgroundProcesses"
- android:description="@string/permdesc_killBackgroundProcesses"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_killBackgroundProcesses"
+ android:description="@string/permdesc_killBackgroundProcesses"
+ android:protectionLevel="normal" />
<!-- Allows an application to call
{@link android.app.ActivityManager#killBackgroundProcesses}.
<p>Protection level: normal
-->
<permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"
- android:label="@string/permlab_killBackgroundProcesses"
- android:description="@string/permdesc_killBackgroundProcesses"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_killBackgroundProcesses"
+ android:description="@string/permdesc_killBackgroundProcesses"
+ android:protectionLevel="normal" />
<!-- @SystemApi @hide Allows an application to query process states and current
OOM adjustment scores.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi @hide Allows an application to retrieve a package's importance.
This permission is not available to third party applications. -->
<permission android:name="android.permission.GET_PACKAGE_IMPORTANCE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows use of PendingIntent.getIntent().
@hide -->
<permission android:name="android.permission.GET_INTENT_SENDER_INTENT"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- ================================== -->
<!-- Permissions affecting the display of other applications -->
@@ -1719,9 +1713,9 @@
Settings.canDrawOverlays()}.
<p>Protection level: signature -->
<permission android:name="android.permission.SYSTEM_ALERT_WINDOW"
- android:label="@string/permlab_systemAlertWindow"
- android:description="@string/permdesc_systemAlertWindow"
- android:protectionLevel="signature|preinstalled|appop|pre23|development" />
+ android:label="@string/permlab_systemAlertWindow"
+ android:description="@string/permdesc_systemAlertWindow"
+ android:protectionLevel="signature|preinstalled|appop|pre23|development" />
<!-- ================================== -->
<!-- Permissions affecting the system wallpaper -->
@@ -1732,17 +1726,17 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.SET_WALLPAPER"
- android:label="@string/permlab_setWallpaper"
- android:description="@string/permdesc_setWallpaper"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_setWallpaper"
+ android:description="@string/permdesc_setWallpaper"
+ android:protectionLevel="normal" />
<!-- Allows applications to set the wallpaper hints.
<p>Protection level: normal
-->
<permission android:name="android.permission.SET_WALLPAPER_HINTS"
- android:label="@string/permlab_setWallpaperHints"
- android:description="@string/permdesc_setWallpaperHints"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_setWallpaperHints"
+ android:description="@string/permdesc_setWallpaperHints"
+ android:protectionLevel="normal" />
<!-- ============================================ -->
<!-- Permissions for changing the system clock -->
@@ -1752,15 +1746,15 @@
<!-- @SystemApi Allows applications to set the system time.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_TIME"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows applications to set the system time zone.
<p>Protection level: normal
-->
<permission android:name="android.permission.SET_TIME_ZONE"
- android:label="@string/permlab_setTimeZone"
- android:description="@string/permdesc_setTimeZone"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_setTimeZone"
+ android:description="@string/permdesc_setTimeZone"
+ android:protectionLevel="normal" />
<!-- ==================================================== -->
<!-- Permissions related to changing status bar -->
@@ -1771,9 +1765,9 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.EXPAND_STATUS_BAR"
- android:label="@string/permlab_expandStatusBar"
- android:description="@string/permdesc_expandStatusBar"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_expandStatusBar"
+ android:description="@string/permdesc_expandStatusBar"
+ android:protectionLevel="normal" />
<!-- ============================================================== -->
<!-- Permissions related to adding/removing shortcuts from Launcher -->
@@ -1784,17 +1778,17 @@
<p>Protection level: normal
-->
<permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
- android:label="@string/permlab_install_shortcut"
- android:description="@string/permdesc_install_shortcut"
- android:protectionLevel="normal"/>
+ android:label="@string/permlab_install_shortcut"
+ android:description="@string/permdesc_install_shortcut"
+ android:protectionLevel="normal"/>
<!-- Allows an application to uninstall a shortcut in Launcher.
<p>Protection level: normal
-->
<permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
- android:label="@string/permlab_uninstall_shortcut"
- android:description="@string/permdesc_uninstall_shortcut"
- android:protectionLevel="normal"/>
+ android:label="@string/permlab_uninstall_shortcut"
+ android:description="@string/permdesc_uninstall_shortcut"
+ android:protectionLevel="normal"/>
<!-- ==================================================== -->
<!-- Permissions related to accessing sync settings -->
@@ -1805,25 +1799,25 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.READ_SYNC_SETTINGS"
- android:description="@string/permdesc_readSyncSettings"
- android:label="@string/permlab_readSyncSettings"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_readSyncSettings"
+ android:label="@string/permlab_readSyncSettings"
+ android:protectionLevel="normal" />
<!-- Allows applications to write the sync settings.
<p>Protection level: normal
-->
<permission android:name="android.permission.WRITE_SYNC_SETTINGS"
- android:description="@string/permdesc_writeSyncSettings"
- android:label="@string/permlab_writeSyncSettings"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_writeSyncSettings"
+ android:label="@string/permlab_writeSyncSettings"
+ android:protectionLevel="normal" />
<!-- Allows applications to read the sync stats.
<p>Protection level: normal
-->
<permission android:name="android.permission.READ_SYNC_STATS"
- android:description="@string/permdesc_readSyncStats"
- android:label="@string/permlab_readSyncStats"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_readSyncStats"
+ android:label="@string/permlab_readSyncStats"
+ android:protectionLevel="normal" />
<!-- ============================================ -->
<!-- Permissions for low-level system interaction -->
@@ -1832,12 +1826,12 @@
<!-- @SystemApi @hide Change the screen compatibility mode of applications -->
<permission android:name="android.permission.SET_SCREEN_COMPATIBILITY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to modify the current configuration, such
as locale. -->
<permission android:name="android.permission.CHANGE_CONFIGURATION"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- Allows an application to read or write the system settings.
@@ -1852,51 +1846,51 @@
<p>Protection level: signature
-->
<permission android:name="android.permission.WRITE_SETTINGS"
- android:label="@string/permlab_writeSettings"
- android:description="@string/permdesc_writeSettings"
- android:protectionLevel="signature|preinstalled|appop|pre23" />
+ android:label="@string/permlab_writeSettings"
+ android:description="@string/permdesc_writeSettings"
+ android:protectionLevel="signature|preinstalled|appop|pre23" />
<!-- @SystemApi Allows an application to modify the Google service map.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.WRITE_GSERVICES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to call
{@link android.app.ActivityManager#forceStopPackage}.
@hide -->
<permission android:name="android.permission.FORCE_STOP_PACKAGES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows an application to retrieve the content of the active window
An active window is the window that has fired an accessibility event. -->
<permission android:name="android.permission.RETRIEVE_WINDOW_CONTENT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Modify the global animation scaling factor.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_ANIMATION_SCALE"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @deprecated This functionality will be removed in the future; please do
not use. Allow an application to make its activities persistent. -->
<permission android:name="android.permission.PERSISTENT_ACTIVITY"
- android:label="@string/permlab_persistentActivity"
- android:description="@string/permdesc_persistentActivity"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_persistentActivity"
+ android:description="@string/permdesc_persistentActivity"
+ android:protectionLevel="normal" />
<!-- Allows an application to find out the space used by any package.
<p>Protection level: normal
-->
<permission android:name="android.permission.GET_PACKAGE_SIZE"
- android:label="@string/permlab_getPackageSize"
- android:description="@string/permdesc_getPackageSize"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_getPackageSize"
+ android:description="@string/permdesc_getPackageSize"
+ android:protectionLevel="normal" />
<!-- @deprecated No longer useful, see
{@link android.content.pm.PackageManager#addPackageToPreferred}
for details. -->
<permission android:name="android.permission.SET_PREFERRED_APPLICATIONS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to receive the
{@link android.content.Intent#ACTION_BOOT_COMPLETED} that is
@@ -1912,9 +1906,9 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"
- android:label="@string/permlab_receiveBootCompleted"
- android:description="@string/permdesc_receiveBootCompleted"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_receiveBootCompleted"
+ android:description="@string/permdesc_receiveBootCompleted"
+ android:protectionLevel="normal" />
<!-- Allows an application to broadcast sticky intents. These are
broadcasts whose data is held by the system after being finished,
@@ -1923,90 +1917,90 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.BROADCAST_STICKY"
- android:label="@string/permlab_broadcastSticky"
- android:description="@string/permdesc_broadcastSticky"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_broadcastSticky"
+ android:description="@string/permdesc_broadcastSticky"
+ android:protectionLevel="normal" />
<!-- @SystemApi Allows mounting and unmounting file systems for removable storage.
<p>Not for use by third-party applications.-->
<permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows formatting file systems for removable storage.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @hide -->
<permission android:name="android.permission.STORAGE_INTERNAL"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows access to ASEC non-destructive API calls
@hide -->
<permission android:name="android.permission.ASEC_ACCESS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows creation of ASEC volumes
@hide -->
<permission android:name="android.permission.ASEC_CREATE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows destruction of ASEC volumes
@hide -->
<permission android:name="android.permission.ASEC_DESTROY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows mount / unmount of ASEC volumes
@hide -->
<permission android:name="android.permission.ASEC_MOUNT_UNMOUNT"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows rename of ASEC volumes
@hide -->
<permission android:name="android.permission.ASEC_RENAME"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows applications to write the apn settings.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.WRITE_APN_SETTINGS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows applications to change network connectivity state.
<p>Protection level: normal
-->
<permission android:name="android.permission.CHANGE_NETWORK_STATE"
- android:description="@string/permdesc_changeNetworkState"
- android:label="@string/permlab_changeNetworkState"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_changeNetworkState"
+ android:label="@string/permlab_changeNetworkState"
+ android:protectionLevel="normal" />
<!-- Allows an application to clear the caches of all installed
applications on the device.
<p>Protection level: system|signature
-->
<permission android:name="android.permission.CLEAR_APP_CACHE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to use any media decoder when decoding for playback
@hide -->
<permission android:name="android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to install and/or uninstall CA certificates on
behalf of the user.
@hide -->
<permission android:name="android.permission.MANAGE_CA_CERTIFICATES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to do certain operations needed for
interacting with the recovery (system update) system.
@hide -->
<permission android:name="android.permission.RECOVERY"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows the system to bind to an application's task services
@hide -->
<permission android:name="android.permission.BIND_JOB_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<uses-permission android:name="android.permission.BIND_JOB_SERVICE"/>
<!-- Allows an application to initiate configuration updates
@@ -2015,12 +2009,7 @@
it off to the various individual installer components
@hide -->
<permission android:name="android.permission.UPDATE_CONFIG"
- android:protectionLevel="signature|privileged" />
-
- <!-- Allows the system to reset throttling in shortcut manager.
- @hide -->
- <permission android:name="android.permission.RESET_SHORTCUT_MANAGER_THROTTLING"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature|privileged" />
<!-- ========================================= -->
<!-- Permissions for special development tools -->
@@ -2030,40 +2019,40 @@
<!-- @SystemApi Allows an application to read or write the secure system settings.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.WRITE_SECURE_SETTINGS"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Allows an application to retrieve state dump information from system services.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.DUMP"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Allows an application to read the low-level system log files.
<p>Not for use by third-party applications, because
Log entries can contain the user's private information. -->
<permission android:name="android.permission.READ_LOGS"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Configure an application for debugging.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_DEBUG_APP"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Allows an application to set the maximum number of (not needed)
application processes that can be running.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_PROCESS_LIMIT"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Allows an application to control whether activities are immediately
finished when put in the background.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.SET_ALWAYS_FINISH"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Allow an application to request that a signal be sent to all persistent processes.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- ==================================== -->
<!-- Private permissions -->
@@ -2072,34 +2061,34 @@
<!-- @SystemApi Allows access to the list of accounts in the Accounts Service. -->
<permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows but does not guarantee access to user passwords at the conclusion of add account
@hide -->
<permission android:name="android.permission.GET_PASSWORD"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows applications to RW to diagnostic resources.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.DIAGNOSTIC"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to open, close, or disable the status bar
and its icons.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.STATUS_BAR"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to be the status bar. Currently used only by SystemUI.apk
@hide -->
<permission android:name="android.permission.STATUS_BAR_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to bind to third party quick settings tiles.
<p>Should only be requested by the System, should be required by
TileService declarations.-->
<permission android:name="android.permission.BIND_QUICK_SETTINGS_TILE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to force a BACK operation on whatever is the
top activity.
@@ -2107,28 +2096,28 @@
@hide
-->
<permission android:name="android.permission.FORCE_BACK"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to update device statistics.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.UPDATE_DEVICE_STATS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi @hide Allows an application to collect battery statistics -->
<permission android:name="android.permission.GET_APP_OPS_STATS"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Allows an application to update application operation statistics. Not for
use by third party apps.
@hide -->
<permission android:name="android.permission.UPDATE_APP_OPS_STATS"
- android:protectionLevel="signature|privileged|installer" />
+ android:protectionLevel="signature|privileged|installer" />
<!-- @SystemApi Allows an application to update the user app op restrictions.
Not for use by third party apps.
@hide -->
<permission android:name="android.permission.MANAGE_APP_OPS_RESTRICTIONS"
- android:protectionLevel="signature|installer" />
+ android:protectionLevel="signature|installer" />
<!-- @SystemApi Allows an application to open windows that are for use by parts
of the system user interface.
@@ -2136,7 +2125,7 @@
@hide
-->
<permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to manage (create, destroy,
Z-order) application tokens in the window manager.
@@ -2144,17 +2133,17 @@
@hide
-->
<permission android:name="android.permission.MANAGE_APP_TOKENS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows System UI to register listeners for events from Window Manager.
@hide -->
<permission android:name="android.permission.REGISTER_WINDOW_MANAGER_LISTENERS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows the application to temporarily freeze the screen for a
full-screen transition. -->
<permission android:name="android.permission.FREEZE_SCREEN"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to inject user events (keys, touch, trackball)
into the event stream and deliver them to ANY window. Without this
@@ -2163,24 +2152,24 @@
@hide
-->
<permission android:name="android.permission.INJECT_EVENTS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows an application to register an input filter which filters the stream
of user events (keys, touch, trackball) before they are dispatched to any window. -->
<permission android:name="android.permission.FILTER_EVENTS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows an application to retrieve the window token from the accessibility manager. -->
<permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows an application to collect frame statistics -->
<permission android:name="android.permission.FRAME_STATS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows an application to temporary enable accessibility on the device. -->
<permission android:name="android.permission.TEMPORARY_ENABLE_ACCESSIBILITY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to watch and control how activities are
started globally in the system. Only for is in debugging
@@ -2189,13 +2178,13 @@
@hide
-->
<permission android:name="android.permission.SET_ACTIVITY_WATCHER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to call the activity manager shutdown() API
to put the higher-level system there into a shutdown state.
@hide -->
<permission android:name="android.permission.SHUTDOWN"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to tell the activity manager to temporarily
stop application switches, putting it into a special mode that
@@ -2203,7 +2192,7 @@
critical UI such as the home screen.
@hide -->
<permission android:name="android.permission.STOP_APP_SWITCHES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to retrieve private information about
the current top activity, such as any assist context it can provide.
@@ -2211,42 +2200,42 @@
@hide
-->
<permission android:name="android.permission.GET_TOP_ACTIVITY_INFO"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to retrieve the current state of keys and
switches.
<p>Not for use by third-party applications.
@deprecated The API that used this permission has been removed. -->
<permission android:name="android.permission.READ_INPUT_STATE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by an {@link android.inputmethodservice.InputMethodService},
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_INPUT_METHOD"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by an {@link android.media.midi.MidiDeviceService},
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_MIDI_DEVICE_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by an {@link android.accessibilityservice.AccessibilityService},
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link android.printservice.PrintService},
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_PRINT_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link android.printservice.recommendation.RecommendationService},
to ensure that only the system can bind to it.
@@ -2255,7 +2244,7 @@
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_PRINT_RECOMMENDATION_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link android.nfc.cardemulation.HostApduService}
or {@link android.nfc.cardemulation.OffHostApduService} to ensure that only
@@ -2263,65 +2252,65 @@
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_NFC_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by the PrintSpooler to ensure that only the system can bind to it.
@hide -->
<permission android:name="android.permission.BIND_PRINT_SPOOLER_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Must be required by the RuntimePermissionPresenterService to ensure
that only the system can bind to it.
@hide -->
<permission android:name="android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a TextService (e.g. SpellCheckerService)
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_TEXT_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link android.net.VpnService},
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_VPN_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link android.service.wallpaper.WallpaperService},
to ensure that only the system can bind to it.
<p>Protection level: system|signature
-->
<permission android:name="android.permission.BIND_WALLPAPER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by a {@link android.service.voice.VoiceInteractionService},
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_VOICE_INTERACTION"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by hotword enrollment application,
to ensure that only the system can interact with it.
@hide <p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.MANAGE_VOICE_KEYPHRASES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by a {@link com.android.media.remotedisplay.RemoteDisplayProvider},
to ensure that only the system can bind to it.
@hide -->
<permission android:name="android.permission.BIND_REMOTE_DISPLAY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link android.media.tv.TvInputService}
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_TV_INPUT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi
Must be required by a {@link com.android.media.tv.remoteprovider.TvRemoteProvider}
@@ -2330,7 +2319,7 @@
<p>Not for use by third-party applications. </p>
@hide -->
<permission android:name="android.permission.BIND_TV_REMOTE_SERVICE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi
Must be required for a virtual remote controller for TV.
@@ -2338,32 +2327,32 @@
<p>Not for use by third-party applications. </p>
@hide -->
<permission android:name="android.permission.TV_VIRTUAL_REMOTE_CONTROLLER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to modify parental controls
<p>Not for use by third-party applications.
@hide -->
<permission android:name="android.permission.MODIFY_PARENTAL_CONTROLS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by a {@link android.media.routing.MediaRouteService}
to ensure that only the system can interact with it.
@hide -->
<permission android:name="android.permission.BIND_ROUTE_PROVIDER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by device administration receiver, to ensure that only the
system can interact with it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_DEVICE_ADMIN"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Required to add or remove another application as a device admin.
<p>Not for use by third-party applications.
@hide -->
<permission android:name="android.permission.MANAGE_DEVICE_ADMINS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows low-level access to setting the orientation (actually
rotation) of the screen.
@@ -2371,33 +2360,33 @@
@hide
-->
<permission android:name="android.permission.SET_ORIENTATION"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows low-level access to setting the pointer speed.
<p>Not for use by third-party applications.
@hide
-->
<permission android:name="android.permission.SET_POINTER_SPEED"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows low-level access to setting input device calibration.
<p>Not for use by normal applications.
@hide -->
<permission android:name="android.permission.SET_INPUT_CALIBRATION"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows low-level access to setting the keyboard layout.
<p>Not for use by third-party applications.
@hide -->
<permission android:name="android.permission.SET_KEYBOARD_LAYOUT"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to query tablet mode state and monitor changes
in it.
<p>Not for use by third-party applications.
@hide -->
<permission android:name="android.permission.TABLET_MODE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to request installing packages. Apps
targeting APIs greater than 22 must hold this permission in
@@ -2405,41 +2394,41 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"
- android:label="@string/permlab_requestInstallPackages"
- android:description="@string/permdesc_requestInstallPackages"
- android:protectionLevel="normal" />
+ android:label="@string/permlab_requestInstallPackages"
+ android:description="@string/permdesc_requestInstallPackages"
+ android:protectionLevel="normal" />
<!-- @SystemApi Allows an application to install packages.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.INSTALL_PACKAGES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to clear user data.
<p>Not for use by third-party applications
@hide
-->
<permission android:name="android.permission.CLEAR_APP_USER_DATA"
- android:protectionLevel="signature|installer" />
+ android:protectionLevel="signature|installer" />
<!-- @hide Allows an application to get the URI permissions
granted to another application.
<p>Not for use by third-party applications
-->
<permission android:name="android.permission.GET_APP_GRANTED_URI_PERMISSIONS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide Allows an application to clear the URI permissions
granted to another application.
<p>Not for use by third-party applications
-->
<permission
- android:name="android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS"
- android:protectionLevel="signature" />
+ android:name="android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS"
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to delete cache files.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.DELETE_CACHE_FILES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to delete packages.
<p>Not for use by third-party applications.
@@ -2447,251 +2436,251 @@
when the application deleting the package is not the same application that installed the
package. -->
<permission android:name="android.permission.DELETE_PACKAGES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to move location of installed package.
@hide -->
<permission android:name="android.permission.MOVE_PACKAGE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to change whether an application component (other than its own) is
enabled or not.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to grant specific permissions.
@hide -->
<permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS"
- android:protectionLevel="signature|installer|verifier" />
+ android:protectionLevel="signature|installer|verifier" />
<!-- @SystemApi Allows an app that has this permission and the permissions to install packages
to request certain runtime permissions to be granted at installation.
@hide -->
<permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS"
- android:protectionLevel="signature|installer|verifier" />
+ android:protectionLevel="signature|installer|verifier" />
<!-- @SystemApi Allows an application to revoke specific permissions.
@hide -->
<permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS"
- android:protectionLevel="signature|installer|verifier" />
+ android:protectionLevel="signature|installer|verifier" />
<!-- @hide Allows an application to observe permission changes. -->
<permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to use SurfaceFlinger's low level features.
<p>Not for use by third-party applications.
@hide
-->
<permission android:name="android.permission.ACCESS_SURFACE_FLINGER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to take screen shots and more generally
get access to the frame buffer data.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.READ_FRAME_BUFFER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to use InputFlinger's low level features.
@hide -->
<permission android:name="android.permission.ACCESS_INPUT_FLINGER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to configure and connect to Wifi displays
@hide -->
<permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to control low-level features of Wifi displays
such as opening an RTSP socket. This permission should only be used
by the display manager.
@hide -->
<permission android:name="android.permission.CONTROL_WIFI_DISPLAY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to control the color transforms applied to
displays system-wide.
<p>Not for use by third-party applications.</p>
@hide -->
<permission android:name="android.permission.CONFIGURE_DISPLAY_COLOR_TRANSFORM"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to control VPN.
<p>Not for use by third-party applications.</p>
@hide -->
<permission android:name="android.permission.CONTROL_VPN"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<uses-permission android:name="android.permission.CONTROL_VPN" />
<!-- @SystemApi Allows an application to capture audio output.
<p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to capture audio for hotword detection.
<p>Not for use by third-party applications.</p>
@hide -->
<permission android:name="android.permission.CAPTURE_AUDIO_HOTWORD"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to modify audio routing and override policy decisions.
<p>Not for use by third-party applications.</p>
@hide -->
<permission android:name="android.permission.MODIFY_AUDIO_ROUTING"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to capture video output.
<p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to capture secure video output.
<p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to know what content is playing and control its playback.
<p>Not for use by third-party applications due to privacy of media consumption</p> -->
<permission android:name="android.permission.MEDIA_CONTENT_CONTROL"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Required to be able to disable the device (very dangerous!).
<p>Not for use by third-party applications.
@hide
-->
<permission android:name="android.permission.BRICK"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Required to be able to reboot the device.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.REBOOT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
- <!-- @SystemApi Allows low-level access to power management.
- <p>Not for use by third-party applications.
- @hide
- -->
- <permission android:name="android.permission.DEVICE_POWER"
- android:protectionLevel="signature" />
+ <!-- @SystemApi Allows low-level access to power management.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.DEVICE_POWER"
+ android:protectionLevel="signature" />
- <!-- Allows access to the PowerManager.userActivity function.
- <p>Not for use by third-party applications. @hide @SystemApi -->
+ <!-- Allows access to the PowerManager.userActivity function.
+ <p>Not for use by third-party applications. @hide @SystemApi -->
<permission android:name="android.permission.USER_ACTIVITY"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
- <!-- @hide Allows low-level access to tun tap driver -->
+ <!-- @hide Allows low-level access to tun tap driver -->
<permission android:name="android.permission.NET_TUNNELING"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Run as a manufacturer test application, running as the root user.
Only available when the device is running in manufacturer test mode.
<p>Not for use by third-party applications.
-->
<permission android:name="android.permission.FACTORY_TEST"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to broadcast a notification that an application
package has been removed.
<p>Not for use by third-party applications.
-->
<permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to broadcast an SMS receipt notification.
<p>Not for use by third-party applications.
-->
<permission android:name="android.permission.BROADCAST_SMS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to broadcast a WAP PUSH receipt notification.
<p>Not for use by third-party applications.
-->
<permission android:name="android.permission.BROADCAST_WAP_PUSH"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to broadcast privileged networking requests.
<p>Not for use by third-party applications. @hide -->
<permission android:name="android.permission.BROADCAST_NETWORK_PRIVILEGED"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Not for use by third-party applications. -->
<permission android:name="android.permission.MASTER_CLEAR"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to call any phone number, including emergency
numbers, without going through the Dialer user interface for the user
to confirm the call being placed.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.CALL_PRIVILEGED"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to perform CDMA OTA provisioning @hide -->
<permission android:name="android.permission.PERFORM_CDMA_PROVISIONING"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to perform SIM Activation @hide -->
<permission android:name="android.permission.PERFORM_SIM_ACTIVATION"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows enabling/disabling location update notifications from
the radio.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.CONTROL_LOCATION_UPDATES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows read/write access to the "properties" table in the checkin
database, to change values that get uploaded.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.ACCESS_CHECKIN_PROPERTIES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to collect component usage
statistics
<p>Declaring the permission implies intention to use the API and the user of the
device can grant permission through the Settings application. -->
<permission android:name="android.permission.PACKAGE_USAGE_STATS"
- android:protectionLevel="signature|privileged|development|appop" />
+ android:protectionLevel="signature|privileged|development|appop" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<!-- @hide Allows an application to change the app idle state of an app.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.CHANGE_APP_IDLE_STATE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @hide @SystemApi Allows an application to temporarily whitelist an inactive app to
access the network and acquire wakelocks.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Permission an application must hold in order to use
{@link android.provider.Settings#ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}.
This is a normal permission: an app requesting it will always be granted the
permission, without the user needing to approve or see it. -->
<permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"
- android:protectionLevel="normal" />
+ android:protectionLevel="normal" />
<!-- @SystemApi Allows an application to collect battery statistics -->
<permission android:name="android.permission.BATTERY_STATS"
- android:protectionLevel="signature|privileged|development" />
+ android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi Allows an application to control the backup and restore process.
<p>Not for use by third-party applications.
@hide pending API council -->
<permission android:name="android.permission.BACKUP"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows a package to launch the secure full-backup confirmation UI.
ONLY the system process may hold this permission.
@hide -->
<permission android:name="android.permission.CONFIRM_FULL_BACKUP"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Must be required by a {@link android.widget.RemoteViewsService},
to ensure that only the system can bind to it. -->
<permission android:name="android.permission.BIND_REMOTEVIEWS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to tell the AppWidget service which application
can access AppWidget's data. The normal user flow is that a user
@@ -2700,25 +2689,25 @@
An application that has this permission should honor that contract.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.BIND_APPWIDGET"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Private permission, to restrict who can bring up a dialog to add a new
keyguard widget
@hide -->
<permission android:name="android.permission.BIND_KEYGUARD_APPWIDGET"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Internal permission allowing an application to query/set which
applications can bind AppWidgets.
@hide -->
<permission android:name="android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows applications to change the background data setting.
<p>Not for use by third-party applications.
@hide pending API council -->
<permission android:name="android.permission.CHANGE_BACKGROUND_DATA_SETTING"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi This permission can be used on content providers to allow the global
search system to access their data. Typically it used when the
@@ -2729,7 +2718,7 @@
it is used by applications to protect themselves from everyone else
besides global search. -->
<permission android:name="android.permission.GLOBAL_SEARCH"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Internal permission protecting access to the global search
system: ensures that only the system can access the provider
@@ -2739,33 +2728,33 @@
ranking).
@hide -->
<permission android:name="android.permission.GLOBAL_SEARCH_CONTROL"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Internal permission to allows an application to read indexable data.
@hide -->
<permission android:name="android.permission.READ_SEARCH_INDEXABLES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows applications to set a live wallpaper.
@hide XXX Change to signature once the picker is moved to its
own apk as Ghod Intended. -->
<permission android:name="android.permission.SET_WALLPAPER_COMPONENT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows applications to read dream settings and dream state.
@hide -->
<permission android:name="android.permission.READ_DREAM_STATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows applications to write dream settings, and start or stop dreaming.
@hide -->
<permission android:name="android.permission.WRITE_DREAM_STATE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allow an application to read and write the cache partition.
@hide -->
<permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by default container service so that only
the system can bind to it and use it to copy
@@ -2773,67 +2762,67 @@
accessible to the system.
@hide -->
<permission android:name="android.permission.COPY_PROTECTED_DATA"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Internal permission protecting access to the encryption methods
@hide
-->
<permission android:name="android.permission.CRYPT_KEEPER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to read historical network usage for
specific networks and applications. @hide -->
<permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to manage network policies (such as warning and disable
limits) and to define application-specific rules. @hide -->
<permission android:name="android.permission.MANAGE_NETWORK_POLICY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to account its network traffic against other UIDs. Used
by system services like download manager and media server. Not for use by
third party apps. @hide -->
<permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- C2DM permission.
@hide Used internally.
-->
<permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<uses-permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"/>
<!-- @SystemApi @hide Package verifier needs to have this permission before the PackageManager will
trust it to verify packages.
-->
<permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by package verifier receiver, to ensure that only the
system can interact with it.
@hide
-->
<permission android:name="android.permission.BIND_PACKAGE_VERIFIER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi @hide Intent filter verifier needs to have this permission before the
PackageManager will trust it to verify intent filters.
-->
<permission android:name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Must be required by intent filter verifier receiver, to ensure that only the
system can interact with it.
@hide
-->
<permission android:name="android.permission.BIND_INTENT_FILTER_VERIFIER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows applications to access serial ports via the SerialManager.
@hide -->
<permission android:name="android.permission.SERIAL_PORT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows the holder to access content providers from outside an ApplicationThread.
This permission is enforced by the ActivityManagerService on the corresponding APIs,
@@ -2842,27 +2831,27 @@
@hide
-->
<permission android:name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to hold an UpdateLock, recommending that a headless
OTA reboot *not* occur while the lock is held.
@hide -->
<permission android:name="android.permission.UPDATE_LOCK"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to read the current set of notifications, including
any metadata and intents attached.
@hide -->
<permission android:name="android.permission.ACCESS_NOTIFICATIONS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Marker permission for applications that wish to access notification policy.
<p>Protection level: normal
-->
<permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"
- android:description="@string/permdesc_access_notification_policy"
- android:label="@string/permlab_access_notification_policy"
- android:protectionLevel="normal" />
+ android:description="@string/permdesc_access_notification_policy"
+ android:label="@string/permlab_access_notification_policy"
+ android:protectionLevel="normal" />
<!-- Allows modification of do not disturb rules and policies. Only allowed for system
processes.
@@ -2873,42 +2862,42 @@
<!-- Allows access to keyguard secure storage. Only allowed for system processes.
@hide -->
<permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows managing (adding, removing) fingerprint templates. Reserved for the system. @hide -->
<permission android:name="android.permission.MANAGE_FINGERPRINT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an app to reset fingerprint attempt counter. Reserved for the system. @hide -->
<permission android:name="android.permission.RESET_FINGERPRINT_LOCKOUT"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to control keyguard. Only allowed for system processes.
@hide -->
<permission android:name="android.permission.CONTROL_KEYGUARD"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to listen to trust changes. Only allowed for system processes.
@hide -->
<permission android:name="android.permission.TRUST_LISTENER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to provide a trust agent.
@hide For security reasons, this is a platform-only permission. -->
<permission android:name="android.permission.PROVIDE_TRUST_AGENT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to launch the trust agent settings activity.
@hide -->
<permission android:name="android.permission.LAUNCH_TRUST_AGENT_SETTINGS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Must be required by an {@link
android.service.trust.TrustAgentService},
to ensure that only the system can bind to it.
@hide -->
<permission android:name="android.permission.BIND_TRUST_AGENT"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by an {@link
android.service.notification.NotificationListenerService},
@@ -2916,7 +2905,7 @@
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by an {@link
android.service.notification.NotificationRankerService to ensure that only the system can bind to it.
@@ -2924,7 +2913,7 @@
@hide This is not a third-party API (intended for system apps). -->
-->
<permission android:name="android.permission.BIND_NOTIFICATION_RANKER_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link
android.service.chooser.ChooserTargetService}, to ensure that
@@ -2932,7 +2921,7 @@
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_CHOOSER_TARGET_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by a {@link
android.service.notification.ConditionProviderService},
@@ -2940,57 +2929,57 @@
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_CONDITION_PROVIDER_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Must be required by an {@link android.service.dreams.DreamService},
to ensure that only the system can bind to it.
<p>Protection level: signature
-->
<permission android:name="android.permission.BIND_DREAM_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to call into a carrier setup flow. It is up to the
carrier setup application to enforce that this permission is required
@hide This is not a third-party API (intended for OEMs and system apps). -->
<permission android:name="android.permission.INVOKE_CARRIER_SETUP"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to listen for network condition observations.
@hide This is not a third-party API (intended for system apps). -->
<permission android:name="android.permission.ACCESS_NETWORK_CONDITIONS"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows an application to provision and access DRM certificates
@hide This is not a third-party API (intended for system apps). -->
<permission android:name="android.permission.ACCESS_DRM_CERTIFICATES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Api Allows an application to manage media projection sessions.
@hide This is not a third-party API (intended for system apps). -->
<permission android:name="android.permission.MANAGE_MEDIA_PROJECTION"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to read install sessions
@hide This is not a third-party API (intended for system apps). -->
<permission android:name="android.permission.READ_INSTALL_SESSIONS"
- android:label="@string/permlab_readInstallSessions"
- android:description="@string/permdesc_readInstallSessions"
- android:protectionLevel="normal"/>
+ android:label="@string/permlab_readInstallSessions"
+ android:description="@string/permdesc_readInstallSessions"
+ android:protectionLevel="normal"/>
<!-- @SystemApi Allows an application to remove DRM certificates
@hide This is not a third-party API (intended for system apps). -->
<permission android:name="android.permission.REMOVE_DRM_CERTIFICATES"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @deprecated Use {@link android.Manifest.permission#BIND_CARRIER_SERVICES} instead -->
<permission android:name="android.permission.BIND_CARRIER_MESSAGING_SERVICE"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to interact with the currently active
{@link android.service.voice.VoiceInteractionService}.
@hide -->
<permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- The system process that is allowed to bind to services in carrier apps will
have this permission. Carrier apps should use this permission to protect
@@ -2998,9 +2987,9 @@
<p>Protection level: system|signature
-->
<permission android:name="android.permission.BIND_CARRIER_SERVICES"
- android:label="@string/permlab_bindCarrierServices"
- android:description="@string/permdesc_bindCarrierServices"
- android:protectionLevel="signature|privileged" />
+ android:label="@string/permlab_bindCarrierServices"
+ android:description="@string/permdesc_bindCarrierServices"
+ android:protectionLevel="signature|privileged" />
<!-- Allows an application to query whether DO_NOT_ASK_CREDENTIALS_ON_BOOT
flag is set.
@@ -3046,7 +3035,7 @@
<!-- Allows the holder to access the ephemeral applications on the device.
@hide -->
<permission android:name="android.permission.ACCESS_EPHEMERAL_APPS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows receiving the usage of media resource e.g. video/audio codec and
graphic memory.
@@ -3058,7 +3047,7 @@
APIs given by {@link SoundTriggerManager}.
@hide <p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.MANAGE_SOUND_TRIGGER"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged" />
<!-- @SystemApi Allows trusted applications to dispatch managed provisioning message to Managed
Provisioning app. If requesting app does not have permission, it will be ignored.
@@ -3082,17 +3071,17 @@
the system can bind to it.
<p>Protection level: signature -->
<permission android:name="android.permission.BIND_VR_LISTENER_SERVICE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Required to make calls to {@link android.service.vr.IVrManager}.
@hide -->
<permission android:name="android.permission.ACCESS_VR_MANAGER"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature" />
<!-- Allows an application to whitelist tasks during lock task mode
@hide <p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.UPDATE_LOCK_TASK_PACKAGES"
- android:protectionLevel="signature|setup" />
+ android:protectionLevel="signature|setup" />
<!-- @SystemApi Allows an application to replace the app name displayed alongside notifications
in the N-release and later.
@@ -3113,13 +3102,12 @@
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true">
<activity android:name="com.android.internal.app.ChooserActivity"
- android:theme="@style/Theme.DeviceDefault.Resolver"
- android:finishOnCloseSystemDialogs="true"
- android:excludeFromRecents="true"
- android:documentLaunchMode="never"
- android:relinquishTaskIdentity="true"
- android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
- android:process=":ui">
+ android:theme="@style/Theme.DeviceDefault.Resolver"
+ android:finishOnCloseSystemDialogs="true"
+ android:excludeFromRecents="true"
+ android:documentLaunchMode="never"
+ android:relinquishTaskIdentity="true"
+ android:process=":ui">
<intent-filter>
<action android:name="android.intent.action.CHOOSER" />
<category android:name="android.intent.category.DEFAULT" />
@@ -3127,102 +3115,102 @@
</intent-filter>
</activity>
<activity android:name="com.android.internal.app.IntentForwarderActivity"
- android:finishOnCloseSystemDialogs="true"
- android:theme="@style/Theme.NoDisplay"
- android:excludeFromRecents="true"
- android:label="@string/user_owner_label"
- android:exported="true"
- >
+ android:finishOnCloseSystemDialogs="true"
+ android:theme="@style/Theme.NoDisplay"
+ android:excludeFromRecents="true"
+ android:label="@string/user_owner_label"
+ android:exported="true"
+ >
</activity>
<activity-alias android:name="com.android.internal.app.ForwardIntentToParent"
- android:targetActivity="com.android.internal.app.IntentForwarderActivity"
- android:exported="true"
- android:label="@string/user_owner_label">
+ android:targetActivity="com.android.internal.app.IntentForwarderActivity"
+ android:exported="true"
+ android:label="@string/user_owner_label">
</activity-alias>
<activity-alias android:name="com.android.internal.app.ForwardIntentToManagedProfile"
- android:targetActivity="com.android.internal.app.IntentForwarderActivity"
- android:icon="@drawable/ic_corp_icon"
- android:exported="true"
- android:label="@string/managed_profile_label">
+ android:targetActivity="com.android.internal.app.IntentForwarderActivity"
+ android:icon="@drawable/ic_corp_icon"
+ android:exported="true"
+ android:label="@string/managed_profile_label">
</activity-alias>
<activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity"
- android:theme="@style/Theme.Material.Light.Dialog"
- android:label="@string/heavy_weight_switcher_title"
- android:finishOnCloseSystemDialogs="true"
- android:excludeFromRecents="true"
- android:process=":ui">
+ android:theme="@style/Theme.Material.Light.Dialog"
+ android:label="@string/heavy_weight_switcher_title"
+ android:finishOnCloseSystemDialogs="true"
+ android:excludeFromRecents="true"
+ android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.PlatLogoActivity"
- android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
- android:configChanges="orientation|keyboardHidden"
- android:process=":ui">
+ android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
+ android:configChanges="orientation|keyboardHidden"
+ android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.DisableCarModeActivity"
- android:theme="@style/Theme.NoDisplay"
- android:excludeFromRecents="true"
- android:process=":ui">
+ android:theme="@style/Theme.NoDisplay"
+ android:excludeFromRecents="true"
+ android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.DumpHeapActivity"
- android:theme="@style/Theme.Translucent.NoTitleBar"
- android:label="@string/dump_heap_title"
- android:finishOnCloseSystemDialogs="true"
- android:noHistory="true"
- android:excludeFromRecents="true"
- android:process=":ui">
+ android:theme="@style/Theme.Translucent.NoTitleBar"
+ android:label="@string/dump_heap_title"
+ android:finishOnCloseSystemDialogs="true"
+ android:noHistory="true"
+ android:excludeFromRecents="true"
+ android:process=":ui">
</activity>
<provider android:name="com.android.server.am.DumpHeapProvider"
- android:authorities="com.android.server.heapdump"
- android:grantUriPermissions="true"
- android:multiprocess="false"
- android:singleUser="true" />
+ android:authorities="com.android.server.heapdump"
+ android:grantUriPermissions="true"
+ android:multiprocess="false"
+ android:singleUser="true" />
<activity android:name="android.accounts.ChooseAccountActivity"
- android:excludeFromRecents="true"
- android:exported="true"
- android:theme="@style/Theme.Material.Light.Dialog"
- android:label="@string/choose_account_label"
- android:process=":ui">
+ android:excludeFromRecents="true"
+ android:exported="true"
+ android:theme="@style/Theme.Material.Light.Dialog"
+ android:label="@string/choose_account_label"
+ android:process=":ui">
</activity>
<activity android:name="android.accounts.ChooseTypeAndAccountActivity"
- android:excludeFromRecents="true"
- android:exported="true"
- android:theme="@style/Theme.Material.Light.Dialog"
- android:label="@string/choose_account_label"
- android:process=":ui">
+ android:excludeFromRecents="true"
+ android:exported="true"
+ android:theme="@style/Theme.Material.Light.Dialog"
+ android:label="@string/choose_account_label"
+ android:process=":ui">
</activity>
<activity android:name="android.accounts.ChooseAccountTypeActivity"
- android:excludeFromRecents="true"
- android:theme="@style/Theme.Material.Light.Dialog"
- android:label="@string/choose_account_label"
- android:process=":ui">
+ android:excludeFromRecents="true"
+ android:theme="@style/Theme.Material.Light.Dialog"
+ android:label="@string/choose_account_label"
+ android:process=":ui">
</activity>
<activity android:name="android.accounts.CantAddAccountActivity"
- android:excludeFromRecents="true"
- android:exported="true"
- android:theme="@style/Theme.Material.Light.Dialog.NoActionBar"
- android:process=":ui">
+ android:excludeFromRecents="true"
+ android:exported="true"
+ android:theme="@style/Theme.Material.Light.Dialog.NoActionBar"
+ android:process=":ui">
</activity>
<activity android:name="android.accounts.GrantCredentialsPermissionActivity"
- android:excludeFromRecents="true"
- android:exported="true"
- android:theme="@style/Theme.Material.Light.DialogWhenLarge"
- android:process=":ui">
+ android:excludeFromRecents="true"
+ android:exported="true"
+ android:theme="@style/Theme.Material.Light.DialogWhenLarge"
+ android:process=":ui">
</activity>
<activity android:name="android.content.SyncActivityTooManyDeletes"
- android:theme="@style/Theme.Material.Light.Dialog"
- android:label="@string/sync_too_many_deletes"
- android:process=":ui">
+ android:theme="@style/Theme.Material.Light.Dialog"
+ android:label="@string/sync_too_many_deletes"
+ android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.ShutdownActivity"
- android:permission="android.permission.SHUTDOWN"
- android:theme="@style/Theme.NoDisplay"
- android:excludeFromRecents="true">
+ android:permission="android.permission.SHUTDOWN"
+ android:theme="@style/Theme.NoDisplay"
+ android:excludeFromRecents="true">
<intent-filter>
<action android:name="android.intent.action.ACTION_REQUEST_SHUTDOWN" />
<category android:name="android.intent.category.DEFAULT" />
@@ -3234,9 +3222,9 @@
</activity>
<activity android:name="com.android.internal.app.NetInitiatedActivity"
- android:theme="@style/Theme.Material.Light.Dialog.Alert"
- android:excludeFromRecents="true"
- android:process=":ui">
+ android:theme="@style/Theme.Material.Light.Dialog.Alert"
+ android:excludeFromRecents="true"
+ android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.SystemUserHomeActivity"
@@ -3253,9 +3241,9 @@
<!-- Activity to prompt user if it's ok to create a new user sandbox for a
specified account. -->
<activity android:name="com.android.internal.app.ConfirmUserCreationActivity"
- android:excludeFromRecents="true"
- android:process=":ui"
- android:theme="@style/Theme.Material.Light.Dialog.Alert">
+ android:excludeFromRecents="true"
+ android:process=":ui"
+ android:theme="@style/Theme.Material.Light.Dialog.Alert">
<intent-filter android:priority="1000">
<action android:name="android.os.action.CREATE_USER" />
<category android:name="android.intent.category.DEFAULT" />
@@ -3263,20 +3251,20 @@
</activity>
<activity android:name="com.android.internal.app.UnlaunchableAppActivity"
- android:theme="@style/Theme.Material.Light.Dialog.Alert"
- android:excludeFromRecents="true"
- android:process=":ui">
+ android:theme="@style/Theme.Material.Light.Dialog.Alert"
+ android:excludeFromRecents="true"
+ android:process=":ui">
</activity>
<receiver android:name="com.android.server.BootReceiver"
- android:systemUserOnly="true">
+ android:systemUserOnly="true">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name="com.android.server.updates.CertPinInstallReceiver"
- android:permission="android.permission.UPDATE_CONFIG">
+ android:permission="android.permission.UPDATE_CONFIG">
<intent-filter>
<action android:name="android.intent.action.UPDATE_PINS" />
<data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3284,7 +3272,7 @@
</receiver>
<receiver android:name="com.android.server.updates.IntentFirewallInstallReceiver"
- android:permission="android.permission.UPDATE_CONFIG">
+ android:permission="android.permission.UPDATE_CONFIG">
<intent-filter>
<action android:name="android.intent.action.UPDATE_INTENT_FIREWALL" />
<data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3292,7 +3280,7 @@
</receiver>
<receiver android:name="com.android.server.updates.SmsShortCodesInstallReceiver"
- android:permission="android.permission.UPDATE_CONFIG">
+ android:permission="android.permission.UPDATE_CONFIG">
<intent-filter>
<action android:name="android.intent.action.UPDATE_SMS_SHORT_CODES" />
<data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3300,7 +3288,7 @@
</receiver>
<receiver android:name="com.android.server.updates.ApnDbInstallReceiver"
- android:permission="android.permission.UPDATE_CONFIG">
+ android:permission="android.permission.UPDATE_CONFIG">
<intent-filter>
<action android:name="android.intent.action.UPDATE_APN_DB" />
<data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3308,7 +3296,7 @@
</receiver>
<receiver android:name="com.android.server.updates.CarrierProvisioningUrlsInstallReceiver"
- android:permission="android.permission.UPDATE_CONFIG">
+ android:permission="android.permission.UPDATE_CONFIG">
<intent-filter>
<action android:name="android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS" />
<data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3316,23 +3304,15 @@
</receiver>
<receiver android:name="com.android.server.updates.TzDataInstallReceiver"
- android:permission="android.permission.UPDATE_CONFIG">
+ android:permission="android.permission.UPDATE_CONFIG">
<intent-filter>
<action android:name="android.intent.action.UPDATE_TZDATA" />
<data android:scheme="content" android:host="*" android:mimeType="*/*" />
</intent-filter>
</receiver>
- <receiver android:name="com.android.server.updates.SELinuxPolicyInstallReceiver"
- android:permission="android.permission.UPDATE_CONFIG">
- <intent-filter>
- <action android:name="android.intent.action.UPDATE_SEPOLICY" />
- <data android:scheme="content" android:host="*" android:mimeType="*/*" />
- </intent-filter>
- </receiver>
-
<receiver android:name="com.android.server.MasterClearReceiver"
- android:permission="android.permission.MASTER_CLEAR">
+ android:permission="android.permission.MASTER_CLEAR">
<intent-filter
android:priority="100" >
<!-- For Checkin, Settings, etc.: action=MASTER_CLEAR -->
@@ -3345,12 +3325,12 @@
</receiver>
<service android:name="android.hardware.location.GeofenceHardwareService"
- android:permission="android.permission.LOCATION_HARDWARE"
- android:exported="false" />
+ android:permission="android.permission.LOCATION_HARDWARE"
+ android:exported="false" />
<service android:name="com.android.internal.backup.LocalTransportService"
- android:permission="android.permission.CONFIRM_FULL_BACKUP"
- android:exported="false">
+ android:permission="android.permission.CONFIRM_FULL_BACKUP"
+ android:exported="false">
<intent-filter>
<action android:name="android.backup.TRANSPORT_HOST" />
</intent-filter>
@@ -3375,9 +3355,9 @@
</service>
<service
- android:name="com.android.server.pm.BackgroundDexOptService"
- android:exported="true"
- android:permission="android.permission.BIND_JOB_SERVICE">
+ android:name="com.android.server.pm.BackgroundDexOptService"
+ android:exported="true"
+ android:permission="android.permission.BIND_JOB_SERVICE">
</service>
</application>
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index e8de02d..7406645 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -106,7 +106,7 @@
// OEMs cannot define permissions in the platform namespace
for (String permission : declaredPermissionsMap.keySet()) {
- assertFalse("Cannot define permission " + permission + " in android namespace",
+ assertFalse("Cannot define permission in android namespace",
permission.startsWith(PLATFORM_ROOT_NAMESPACE));
}
diff --git a/tests/tests/print/Android.mk b/tests/tests/print/Android.mk
index bceaacc..d0c1a81 100644
--- a/tests/tests/print/Android.mk
+++ b/tests/tests/print/Android.mk
@@ -27,7 +27,7 @@
LOCAL_PACKAGE_NAME := CtsPrintTestCases
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ctstestrunner ub-uiautomator ctsdeviceutil
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ctstestrunner ub-uiautomator ctsdeviceutil android-support-test
LOCAL_SDK_VERSION := test_current
diff --git a/tests/tests/print/src/android/print/cts/AppPrintInterfaceTest.java b/tests/tests/print/src/android/print/cts/AppPrintInterfaceTest.java
new file mode 100644
index 0000000..98434bb
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/AppPrintInterfaceTest.java
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.print.cts;
+
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+import android.print.PageRange;
+import android.print.PrintAttributes;
+import android.print.PrintDocumentAdapter;
+import android.print.PrintDocumentInfo;
+import android.print.PrintJob;
+import android.print.PrintJobInfo;
+import android.print.PrintManager;
+import android.print.PrinterCapabilitiesInfo;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+import android.print.cts.services.FirstPrintService;
+import android.print.cts.services.PrintServiceCallbacks;
+import android.print.cts.services.PrinterDiscoverySessionCallbacks;
+import android.print.cts.services.SecondPrintService;
+import android.print.cts.services.StubbablePrinterDiscoverySession;
+import android.support.annotation.NonNull;
+
+import java.util.ArrayList;
+
+/**
+ * Test interface from the application to the print service.
+ */
+public class AppPrintInterfaceTest extends BasePrintTest {
+ private static final String TEST_PRINTER = "Test printer";
+
+ private static final PrintAttributes.Resolution TWO_HUNDRED_DPI = new PrintAttributes.Resolution(
+ "200x200", "200dpi", 200,
+ 200);
+
+ /**
+ * @return The print manager
+ */
+ private @NonNull PrintManager getPrintManager() {
+ return (PrintManager) getActivity().getSystemService(Context.PRINT_SERVICE);
+ }
+
+ /**
+ * Start printing
+ *
+ * @param adapter Adapter supplying data to print
+ * @param printJobName The name of the print job
+ */
+ protected void print(@NonNull PrintDocumentAdapter adapter, @NonNull String printJobName) {
+ // Initiate printing as if coming from the app.
+ getInstrumentation()
+ .runOnMainSync(() -> getPrintManager().print(printJobName, adapter, null));
+ }
+
+ /**
+ * Create a mock {@link PrintDocumentAdapter} that provides one empty page.
+ *
+ * @return The mock adapter
+ */
+ private @NonNull PrintDocumentAdapter createMockPrintDocumentAdapter() {
+ final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+ return createMockPrintDocumentAdapter(
+ invocation -> {
+ printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+ PrintDocumentAdapter.LayoutResultCallback callback =
+ (PrintDocumentAdapter.LayoutResultCallback) invocation
+ .getArguments()[3];
+
+ callback.onLayoutFinished(new PrintDocumentInfo.Builder("doc")
+ .setPageCount(1).build(), false);
+
+ onLayoutCalled();
+ return null;
+ }, invocation -> {
+ Object[] args = invocation.getArguments();
+ PageRange[] pages = (PageRange[]) args[0];
+ ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
+ PrintDocumentAdapter.WriteResultCallback callback = (PrintDocumentAdapter.WriteResultCallback) args[3];
+
+ writeBlankPages(printAttributes[0], fd, pages[0].getStart(), pages[0].getEnd());
+ fd.close();
+ callback.onWriteFinished(pages);
+ return null;
+ }, invocation -> null);
+ }
+
+ /**
+ * Create a mock {@link PrinterDiscoverySessionCallbacks} that discovers a simple test printer.
+ *
+ * @return The mock session callbacks
+ */
+ private @NonNull PrinterDiscoverySessionCallbacks createFirstMockPrinterDiscoverySessionCallbacks() {
+ return createMockPrinterDiscoverySessionCallbacks(invocation -> {
+ StubbablePrinterDiscoverySession session = ((PrinterDiscoverySessionCallbacks) invocation
+ .getMock()).getSession();
+
+ if (session.getPrinters().isEmpty()) {
+ PrinterId printerId = session.getService().generatePrinterId(TEST_PRINTER);
+ PrinterInfo.Builder printer = new PrinterInfo.Builder(
+ session.getService().generatePrinterId(TEST_PRINTER), TEST_PRINTER,
+ PrinterInfo.STATUS_IDLE);
+
+ printer.setCapabilities(new PrinterCapabilitiesInfo.Builder(printerId)
+ .addMediaSize(PrintAttributes.MediaSize.ISO_A5, true)
+ .addResolution(TWO_HUNDRED_DPI, true)
+ .setColorModes(PrintAttributes.COLOR_MODE_MONOCHROME,
+ PrintAttributes.COLOR_MODE_MONOCHROME)
+ .setMinMargins(new PrintAttributes.Margins(0, 0, 0, 0)).build());
+
+ ArrayList<PrinterInfo> printers = new ArrayList<>(1);
+ printers.add(printer.build());
+
+ session.addPrinters(printers);
+ }
+ return null;
+ }, null, null, invocation -> null, null, null, invocation -> {
+ // Take a note onDestroy was called.
+ onPrinterDiscoverySessionDestroyCalled();
+ return null;
+ });
+ }
+
+ /**
+ * Create mock service callback for a session. Once the job is queued the test function is
+ * called.
+ *
+ * @param sessionCallbacks The callbacks of the session
+ * @param blockAfterState The state the print services should progress to
+ */
+ private @NonNull PrintServiceCallbacks createFirstMockPrinterServiceCallbacks(
+ final @NonNull PrinterDiscoverySessionCallbacks sessionCallbacks, int blockAfterState) {
+ return createMockPrintServiceCallbacks(
+ invocation -> sessionCallbacks, invocation -> {
+ android.printservice.PrintJob job = (android.printservice.PrintJob) invocation
+ .getArguments()[0];
+
+ switch (blockAfterState) {
+ case PrintJobInfo.STATE_CREATED:
+ assertEquals(PrintJobInfo.STATE_CREATED, job.getInfo().getState());
+ break;
+ case PrintJobInfo.STATE_STARTED:
+ job.start();
+ break;
+ case PrintJobInfo.STATE_QUEUED:
+ assertEquals(PrintJobInfo.STATE_QUEUED, job.getInfo().getState());
+ break;
+ case PrintJobInfo.STATE_BLOCKED:
+ job.start();
+ job.block("test block");
+ break;
+ case PrintJobInfo.STATE_FAILED:
+ job.start();
+ job.fail("test fail");
+ break;
+ case PrintJobInfo.STATE_COMPLETED:
+ job.start();
+ job.complete();
+ break;
+ default:
+ throw new Exception("Should not be reached");
+ }
+
+ return null;
+ }, invocation -> {
+ android.printservice.PrintJob job = (android.printservice.PrintJob) invocation
+ .getArguments()[0];
+
+ job.cancel();
+
+ return null;
+ });
+ }
+
+ /**
+ * Setup mock print subsystem
+ *
+ * @param blockAfterState Tell the print service to block all print jobs at this state
+ *
+ * @return The print document adapter to be used for printing
+ */
+ private @NonNull PrintDocumentAdapter setupPrint(int blockAfterState) {
+ // Create the session of the printers that we will be checking.
+ PrinterDiscoverySessionCallbacks sessionCallbacks = createFirstMockPrinterDiscoverySessionCallbacks();
+
+ // Create the service callbacks for the first print service.
+ PrintServiceCallbacks serviceCallbacks = createFirstMockPrinterServiceCallbacks(
+ sessionCallbacks, blockAfterState);
+
+ // Configure the print services.
+ FirstPrintService.setCallbacks(serviceCallbacks);
+
+ // We don't use the second service, but we have to still configure it
+ SecondPrintService.setCallbacks(createMockPrintServiceCallbacks(null, null, null));
+
+ return createMockPrintDocumentAdapter();
+ }
+
+ /**
+ * @param name Name of print job
+ *
+ * @return The print job for the name
+ *
+ * @throws Exception If print job could not be found
+ */
+ private @NonNull PrintJob getPrintJob(@NonNull String name) throws Exception {
+ for (PrintJob job : getPrintManager().getPrintJobs()) {
+ if (job.getInfo().getLabel().equals(name)) {
+ return job;
+ }
+ }
+
+ throw new Exception(
+ "Print job " + name + " not found in " + getPrintManager().getPrintJobs());
+ }
+
+ /**
+ * Base test for all cancel print job tests
+ *
+ * @param cancelAfterState The print job state state to progress to canceling
+ * @param printJobName The print job name to use
+ *
+ * @throws Exception If anything is unexpected
+ */
+ private void cancelPrintJobBaseTest(int cancelAfterState, @NonNull String printJobName)
+ throws Exception {
+ PrintDocumentAdapter adapter = setupPrint(cancelAfterState);
+
+ print(adapter, printJobName);
+ selectPrinter(TEST_PRINTER);
+
+ clickPrintButton();
+ answerPrintServicesWarning(true);
+
+ PrintJob job = getPrintJob(printJobName);
+
+ eventually(() -> assertEquals(cancelAfterState, job.getInfo().getState()));
+
+ job.cancel();
+
+ eventually(() -> assertEquals(PrintJobInfo.STATE_CANCELED, job.getInfo().getState()));
+
+ waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
+ }
+
+ public void testAttemptCancelCreatedPrintJob() throws Exception {
+ PrintDocumentAdapter adapter = setupPrint(PrintJobInfo.STATE_STARTED);
+
+ print(adapter, "testAttemptCancelCreatedPrintJob");
+ selectPrinter(TEST_PRINTER);
+
+ waitForLayoutAdapterCallbackCount(1);
+
+ PrintJob job = getPrintJob("testAttemptCancelCreatedPrintJob");
+
+ // Cancel does not have an effect on created jobs
+ job.cancel();
+
+ eventually(() -> assertEquals(PrintJobInfo.STATE_CREATED, job.getInfo().getState()));
+
+ // Cancel printing by exiting print activity
+ getUiDevice().pressBack();
+
+ eventually(() -> assertEquals(PrintJobInfo.STATE_CANCELED, job.getInfo().getState()));
+
+ waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
+ }
+
+ public void testCancelStartedPrintJob() throws Exception {
+ cancelPrintJobBaseTest(PrintJobInfo.STATE_STARTED, "testCancelStartedPrintJob");
+ }
+
+ public void testCancelBlockedPrintJob() throws Exception {
+ cancelPrintJobBaseTest(PrintJobInfo.STATE_BLOCKED, "testCancelBlockedPrintJob");
+ }
+
+ public void testCancelFailedPrintJob() throws Exception {
+ cancelPrintJobBaseTest(PrintJobInfo.STATE_FAILED, "testCancelFailedPrintJob");
+ }
+
+ public void testRestartFailedPrintJob() throws Exception {
+ PrintDocumentAdapter adapter = setupPrint(PrintJobInfo.STATE_FAILED);
+
+ print(adapter, "testRestartFailedPrintJob");
+ selectPrinter(TEST_PRINTER);
+
+ clickPrintButton();
+ answerPrintServicesWarning(true);
+
+ PrintJob job = getPrintJob("testRestartFailedPrintJob");
+
+ eventually(() -> assertEquals(PrintJobInfo.STATE_FAILED, job.getInfo().getState()));
+
+ // Restart goes from failed right to queued, so stop the print job at "queued" now
+ setupPrint(PrintJobInfo.STATE_QUEUED);
+
+ job.restart();
+ eventually(() -> assertEquals(PrintJobInfo.STATE_QUEUED, job.getInfo().getState()));
+
+ job.cancel();
+ eventually(() -> assertEquals(PrintJobInfo.STATE_CANCELED, job.getInfo().getState()));
+
+ waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
+ }
+
+ public void testGetTwoPrintJobStates() throws Exception {
+ PrintDocumentAdapter adapter = setupPrint(PrintJobInfo.STATE_BLOCKED);
+ print(adapter, "testGetTwoPrintJobStates-block");
+ selectPrinter(TEST_PRINTER);
+ clickPrintButton();
+ answerPrintServicesWarning(true);
+
+ PrintJob job1 = getPrintJob("testGetTwoPrintJobStates-block");
+ eventually(() -> assertEquals(PrintJobInfo.STATE_BLOCKED, job1.getInfo().getState()));
+
+ adapter = setupPrint(PrintJobInfo.STATE_COMPLETED);
+ print(adapter, "testGetTwoPrintJobStates-complete");
+ clickPrintButton();
+
+ PrintJob job2 = getPrintJob("testGetTwoPrintJobStates-complete");
+ eventually(() -> assertEquals(PrintJobInfo.STATE_COMPLETED, job2.getInfo().getState()));
+
+ // First print job should still be there
+ PrintJob job1again = getPrintJob("testGetTwoPrintJobStates-block");
+ assertEquals(PrintJobInfo.STATE_BLOCKED, job1again.getInfo().getState());
+
+ // Check attributes that should have been applied
+ assertEquals(PrintAttributes.MediaSize.ISO_A5,
+ job1again.getInfo().getAttributes().getMediaSize());
+ assertEquals(PrintAttributes.COLOR_MODE_MONOCHROME,
+ job1again.getInfo().getAttributes().getColorMode());
+ assertEquals(TWO_HUNDRED_DPI, job1again.getInfo().getAttributes().getResolution());
+
+ waitForPrinterDiscoverySessionDestroyCallbackCalled(2);
+ }
+}
diff --git a/tests/tests/print/src/android/print/cts/BasePrintTest.java b/tests/tests/print/src/android/print/cts/BasePrintTest.java
index 7f0ae5d..8f2949e 100644
--- a/tests/tests/print/src/android/print/cts/BasePrintTest.java
+++ b/tests/tests/print/src/android/print/cts/BasePrintTest.java
@@ -55,7 +55,6 @@
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiSelector;
import android.test.InstrumentationTestCase;
-import android.util.DisplayMetrics;
import android.util.Log;
import org.hamcrest.BaseMatcher;
@@ -71,7 +70,6 @@
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
-import java.util.Locale;
import java.util.concurrent.TimeoutException;
/**
* This is the base class for print tests.
@@ -87,11 +85,41 @@
private static final String COMMAND_PREFIX_ENABLE_IME = "ime enable ";
private static final String COMMAND_PREFIX_DISABLE_IME = "ime disable ";
private static final int CURRENT_USER_ID = -2; // Mirrors UserHandle.USER_CURRENT
+ private static final String PRINTSPOOLER_PACKAGE = "com.android.printspooler";
private static PrintDocumentActivity sActivity;
private UiDevice mUiDevice;
/**
+ * Make sure that a runnable eventually finishes without throwing a exception.
+ *
+ * @param r The runnable to run.
+ */
+ protected static void eventually(Runnable r) {
+ final long TIMEOUT_MILLS = 5000;
+ long start = System.currentTimeMillis();
+
+ while (true) {
+ try {
+ r.run();
+ break;
+ } catch (Throwable e) {
+ if (System.currentTimeMillis() - start < TIMEOUT_MILLS) {
+ Log.e(LOG_TAG, "Ignoring exception", e);
+
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e1) {
+ Log.e(LOG_TAG, "Interrupted", e);
+ }
+ } else {
+ throw e;
+ }
+ }
+ }
+ }
+
+ /**
* Return the UI device
*
* @return the UI device
@@ -100,8 +128,6 @@
return mUiDevice;
}
- private LocaleList mOldLocale;
-
private CallCounter mCancelOperationCounter;
private CallCounter mLayoutCallCounter;
private CallCounter mWriteCallCounter;
@@ -180,18 +206,6 @@
System.setProperty("dexmaker.dexcache", getInstrumentation()
.getTargetContext().getCacheDir().getPath());
- // Set to US locale.
- Log.d(LOG_TAG, "set locale");
- Resources resources = getInstrumentation().getTargetContext().getResources();
- Configuration oldConfiguration = resources.getConfiguration();
- if (!oldConfiguration.getLocales().get(0).equals(Locale.US)) {
- mOldLocale = oldConfiguration.getLocales();
- DisplayMetrics displayMetrics = resources.getDisplayMetrics();
- Configuration newConfiguration = new Configuration(oldConfiguration);
- newConfiguration.setLocale(Locale.US);
- resources.updateConfiguration(newConfiguration, displayMetrics);
- }
-
// Initialize the latches.
Log.d(LOG_TAG, "init counters");
mCancelOperationCounter = new CallCounter();
@@ -226,17 +240,6 @@
Log.d(LOG_TAG, "enableImes()");
enableImes();
- // Restore the locale if needed.
- Log.d(LOG_TAG, "restore locale");
- if (mOldLocale != null) {
- Resources resources = getInstrumentation().getTargetContext().getResources();
- DisplayMetrics displayMetrics = resources.getDisplayMetrics();
- Configuration newConfiguration = new Configuration(resources.getConfiguration());
- newConfiguration.setLocales(mOldLocale);
- mOldLocale = null;
- resources.updateConfiguration(newConfiguration, displayMetrics);
- }
-
// Make sure the spooler is cleaned, this also un-approves all services
Log.d(LOG_TAG, "clearPrintSpoolerData()");
clearPrintSpoolerData();
@@ -439,12 +442,11 @@
}
protected void answerPrintServicesWarning(boolean confirm) throws UiObjectNotFoundException {
- UiDevice uiDevice = UiDevice.getInstance(getInstrumentation());
UiObject button;
if (confirm) {
- button = uiDevice.findObject(new UiSelector().resourceId("android:id/button1"));
+ button = mUiDevice.findObject(new UiSelector().resourceId("android:id/button1"));
} else {
- button = uiDevice.findObject(new UiSelector().resourceId("android:id/button2"));
+ button = mUiDevice.findObject(new UiSelector().resourceId("android:id/button2"));
}
button.click();
}
@@ -568,6 +570,17 @@
}
}
+ protected void clickRetryButton() throws UiObjectNotFoundException, IOException {
+ try {
+ UiObject retryButton = mUiDevice.findObject(new UiSelector().resourceId(
+ "com.android.printspooler:id/action_button"));
+ retryButton.click();
+ } catch (UiObjectNotFoundException e) {
+ dumpWindowHierarchy();
+ throw e;
+ }
+ }
+
protected void dumpWindowHierarchy() throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
mUiDevice.dumpWindowHierarchy(os);
@@ -807,4 +820,76 @@
return getInstrumentation().getContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_PRINTING);
}
+
+ /**
+ * Get a string array from the print spooler's resources.
+ *
+ * @param resourceName The name of the array resource
+ * @return The localized string array
+ *
+ * @throws Exception If anything is unexpected
+ */
+ protected String[] getPrintSpoolerStringArray(String resourceName) throws Exception {
+ PackageManager pm = getActivity().getPackageManager();
+ Resources printSpoolerRes = pm.getResourcesForApplication(PRINTSPOOLER_PACKAGE);
+ int id = printSpoolerRes.getIdentifier(resourceName, "array", PRINTSPOOLER_PACKAGE);
+ return printSpoolerRes.getStringArray(id);
+ }
+
+ /**
+ * Get a string from the print spooler's resources.
+ *
+ * @param resource_name The name of the string resource
+ * @return The localized string
+ *
+ * @throws Exception If anything is unexpected
+ */
+ protected String getPrintSpoolerString(String resourceName) throws Exception {
+ PackageManager pm = getActivity().getPackageManager();
+ Resources printSpoolerRes = pm.getResourcesForApplication(PRINTSPOOLER_PACKAGE);
+ int id = printSpoolerRes.getIdentifier(resourceName, "string", PRINTSPOOLER_PACKAGE);
+ return printSpoolerRes.getString(id);
+ }
+
+ /**
+ * Get a string with one parameter from the print spooler's resources.
+ *
+ * @param resource_name The name of the string resource
+ * @return The localized string
+ *
+ * @throws Exception If anything is unexpected
+ */
+ protected String getPrintSpoolerStringOneParam(String resourceName, Object p)
+ throws Exception {
+ PackageManager pm = getActivity().getPackageManager();
+ Resources printSpoolerRes = pm.getResourcesForApplication(PRINTSPOOLER_PACKAGE);
+ int id = printSpoolerRes.getIdentifier(resourceName, "string", PRINTSPOOLER_PACKAGE);
+ return printSpoolerRes.getString(id, p);
+ }
+
+ /**
+ * Get the default media size for the current locale.
+ *
+ * @return The default media size for the current locale
+ *
+ * @throws Exception If anything is unexpected
+ */
+ protected PrintAttributes.MediaSize getDefaultMediaSize() throws Exception {
+ PackageManager pm = getActivity().getPackageManager();
+ Resources printSpoolerRes = pm.getResourcesForApplication(PRINTSPOOLER_PACKAGE);
+ int defaultMediaSizeResId = printSpoolerRes.getIdentifier("mediasize_default", "string",
+ PRINTSPOOLER_PACKAGE);
+ String defaultMediaSizeName = printSpoolerRes.getString(defaultMediaSizeResId);
+
+ switch (defaultMediaSizeName) {
+ case "NA_LETTER":
+ return PrintAttributes.MediaSize.NA_LETTER;
+ case "JIS_B5":
+ return PrintAttributes.MediaSize.JIS_B5;
+ case "ISO_A4":
+ return PrintAttributes.MediaSize.ISO_A4;
+ default:
+ throw new Exception("Unknown default media size " + defaultMediaSizeName);
+ }
+ }
}
diff --git a/tests/tests/print/src/android/print/cts/CustomPrintOptionsTest.java b/tests/tests/print/src/android/print/cts/CustomPrintOptionsTest.java
index 54b4d23..68f6201 100644
--- a/tests/tests/print/src/android/print/cts/CustomPrintOptionsTest.java
+++ b/tests/tests/print/src/android/print/cts/CustomPrintOptionsTest.java
@@ -87,7 +87,8 @@
* @throws Exception If something was unexpected
*/
private PageRange[] getPages() throws Exception {
- if (getUiDevice().hasObject(By.text("All 3"))) {
+ if (getUiDevice().hasObject(By.text(getPrintSpoolerStringOneParam("template_all_pages",
+ 3)))) {
return PAGESS[2];
}
diff --git a/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java b/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java
index df142b9..dae2976 100644
--- a/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java
+++ b/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java
@@ -258,7 +258,7 @@
waitForLayoutAdapterCallbackCount(2);
// Select only the second page.
- selectPages("2");
+ selectPages("2", PAGE_COUNT);
// Click the print button.
clickPrintButton();
@@ -392,7 +392,7 @@
waitForLayoutAdapterCallbackCount(2);
// Select a page not written for preview.
- selectPages(Integer.valueOf(REQUESTED_PAGE).toString());
+ selectPages(Integer.valueOf(REQUESTED_PAGE).toString(), PAGE_COUNT);
// Click the print button.
clickPrintButton();
@@ -607,7 +607,7 @@
waitForLayoutAdapterCallbackCount(2);
// Select a page not written for preview.
- selectPages("3");
+ selectPages("3", PAGE_COUNT);
// Click the print button.
clickPrintButton();
@@ -633,12 +633,13 @@
any(PrintJob.class));
}
- private void selectPages(String pages) throws UiObjectNotFoundException {
+ private void selectPages(String pages, int totalPages) throws Exception {
UiObject pagesSpinner = getUiDevice().findObject(new UiSelector().resourceId(
"com.android.printspooler:id/range_options_spinner"));
pagesSpinner.click();
- UiObject rangeOption = getUiDevice().findObject(new UiSelector().textContains("Range"));
+ UiObject rangeOption = getUiDevice().findObject(new UiSelector().textContains(
+ getPrintSpoolerStringOneParam("template_page_range", totalPages)));
rangeOption.click();
UiObject pagesEditText = getUiDevice().findObject(new UiSelector().resourceId(
diff --git a/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java b/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
index f171884..fd656ce 100644
--- a/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
+++ b/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
@@ -43,6 +43,7 @@
import android.print.cts.services.StubbablePrinterDiscoverySession;
import android.printservice.PrintJob;
import android.printservice.PrintService;
+import android.util.Log;
import org.mockito.InOrder;
import org.mockito.invocation.InvocationOnMock;
@@ -58,6 +59,8 @@
*/
public class PrintDocumentAdapterContractTest extends BasePrintTest {
+ private static final String LOG_TAG = "PrintDocumentAdapterContractTest";
+
public void testNoPrintOptionsOrPrinterChange() throws Exception {
if (!supportsPrinting()) {
return;
@@ -141,7 +144,7 @@
// there are other printers but none of them was used.
PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.NA_LETTER)
+ .setMediaSize(getDefaultMediaSize())
.setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
.setMinMargins(Margins.NO_MARGINS)
.setColorMode(PrintAttributes.COLOR_MODE_COLOR)
@@ -256,7 +259,7 @@
// there are other printers but none of them was used.
PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.NA_LETTER)
+ .setMediaSize(getDefaultMediaSize())
.setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
.setMinMargins(Margins.NO_MARGINS)
.setColorMode(PrintAttributes.COLOR_MODE_COLOR)
@@ -342,25 +345,25 @@
waitForLayoutAdapterCallbackCount(2);
// Change the orientation.
- changeOrientation("Landscape");
+ changeOrientation(getPrintSpoolerStringArray("orientation_labels")[1]);
// Wait for layout.
waitForLayoutAdapterCallbackCount(3);
// Change the media size.
- changeMediaSize("ISO A4");
+ changeMediaSize(MediaSize.ISO_A0.getLabel(getActivity().getPackageManager()));
// Wait for layout.
waitForLayoutAdapterCallbackCount(4);
// Change the color.
- changeColor("Black & White");
+ changeColor(getPrintSpoolerStringArray("color_mode_labels")[0]);
// Wait for layout.
waitForLayoutAdapterCallbackCount(5);
// Change the duplex.
- changeDuplex("Short edge");
+ changeDuplex(getPrintSpoolerStringArray("duplex_mode_labels")[2]);
// Wait for layout.
waitForLayoutAdapterCallbackCount(6);
@@ -387,7 +390,7 @@
// there are other printers but none of them was used.
PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.NA_LETTER)
+ .setMediaSize(getDefaultMediaSize())
.setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
.setMinMargins(Margins.NO_MARGINS)
.setColorMode(PrintAttributes.COLOR_MODE_COLOR)
@@ -432,7 +435,7 @@
// there shouldn't be a next call to write.
PrintAttributes fourthOldAttributes = thirdNewAttributes;
PrintAttributes fourthNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.ISO_A4.asLandscape())
+ .setMediaSize(MediaSize.ISO_A0.asLandscape())
.setResolution(new Resolution("300x300", "300x300", 300, 300))
.setMinMargins(Margins.NO_MARGINS)
.setColorMode(PrintAttributes.COLOR_MODE_COLOR)
@@ -445,7 +448,7 @@
// there shouldn't be a next call to write.
PrintAttributes fifthOldAttributes = fourthNewAttributes;
PrintAttributes fifthNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.ISO_A4.asLandscape())
+ .setMediaSize(MediaSize.ISO_A0.asLandscape())
.setResolution(new Resolution("300x300", "300x300", 300, 300))
.setMinMargins(Margins.NO_MARGINS)
.setColorMode(PrintAttributes.COLOR_MODE_MONOCHROME)
@@ -458,7 +461,7 @@
// there shouldn't be a next call to write.
PrintAttributes sixthOldAttributes = fifthNewAttributes;
PrintAttributes sixthNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.ISO_A4.asLandscape())
+ .setMediaSize(MediaSize.ISO_A0.asLandscape())
.setResolution(new Resolution("300x300", "300x300", 300, 300))
.setMinMargins(Margins.NO_MARGINS)
.setColorMode(PrintAttributes.COLOR_MODE_MONOCHROME)
@@ -546,7 +549,7 @@
waitForLayoutAdapterCallbackCount(2);
// Change the color.
- changeColor("Black & White");
+ changeColor(getPrintSpoolerStringArray("color_mode_labels")[0]);
// Wait for layout.
waitForLayoutAdapterCallbackCount(3);
@@ -580,7 +583,7 @@
// there are other printers but none of them was used.
PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.NA_LETTER)
+ .setMediaSize(getDefaultMediaSize())
.setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
.setMinMargins(Margins.NO_MARGINS)
.setColorMode(PrintAttributes.COLOR_MODE_COLOR)
@@ -622,7 +625,7 @@
// new printer which results in a layout pass. Same for color.
PrintAttributes fourthOldAttributes = thirdNewAttributes;
PrintAttributes fourthNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.ISO_A4)
+ .setMediaSize(MediaSize.ISO_A0)
.setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
.setMinMargins(new Margins(200, 200, 200, 200))
.setColorMode(PrintAttributes.COLOR_MODE_COLOR)
@@ -732,7 +735,7 @@
// there are other printers but none of them was used.
PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.NA_LETTER)
+ .setMediaSize(getDefaultMediaSize())
.setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
.setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
.setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -860,7 +863,7 @@
// there are other printers but none of them was used.
PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.NA_LETTER)
+ .setMediaSize(getDefaultMediaSize())
.setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
.setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
.setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -973,7 +976,7 @@
// there are other printers but none of them was used.
PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.NA_LETTER)
+ .setMediaSize(getDefaultMediaSize())
.setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
.setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
.setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -1081,7 +1084,7 @@
// there are other printers but none of them was used.
PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.NA_LETTER)
+ .setMediaSize(getDefaultMediaSize())
.setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
.setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
.setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -1176,7 +1179,7 @@
// there are other printers but none of them was used.
PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.NA_LETTER)
+ .setMediaSize(getDefaultMediaSize())
.setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
.setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
.setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -1249,7 +1252,7 @@
// there are other printers but none of them was used.
PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.NA_LETTER)
+ .setMediaSize(getDefaultMediaSize())
.setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
.setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
.setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -1332,7 +1335,7 @@
// there are other printers but none of them was used.
PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.NA_LETTER)
+ .setMediaSize(getDefaultMediaSize())
.setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
.setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
.setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -1351,6 +1354,168 @@
verifyNoMoreInteractions(adapter);
}
+ public void testUnexpectedLayoutCancel() throws Exception {
+ if (!supportsPrinting()) {
+ return;
+ }
+ // Configure the print services.
+ FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+ SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+ final PrintAttributes[] printAttributes = new PrintAttributes[1];
+ final int[] numLayoutCalls = new int[1];
+
+ // Create a mock print adapter.
+ final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+ new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+ LayoutResultCallback callback = (LayoutResultCallback) invocation.getArguments()[3];
+
+ // Returned cancelled for the second layout call which is unexpected
+ if (numLayoutCalls[0] == 1) {
+ callback.onLayoutCancelled();
+ } else {
+ callback.onLayoutFinished(
+ (new PrintDocumentInfo.Builder(PRINT_JOB_NAME)).build(), false);
+ }
+ numLayoutCalls[0]++;
+ // Mark layout was called.
+ onLayoutCalled();
+ return null;
+ }
+ }, new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ PageRange[] pages = (PageRange[]) args[0];
+ ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
+ WriteResultCallback callback = (WriteResultCallback) args[3];
+ writeBlankPages(printAttributes[0], fd, 0, 1);
+ fd.close();
+ callback.onWriteFinished(pages);
+ // Mark write was called.
+ onWriteCalled();
+ return null;
+ }
+ }, new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ // Mark finish was called.
+ onFinishCalled();
+ return null;
+ }
+ });
+
+ // Start printing.
+ print(adapter);
+
+ // Wait for layout.
+ waitForLayoutAdapterCallbackCount(1);
+
+ // Select the second printer.
+ selectPrinter("Second printer");
+
+ // Wait for layout.
+ waitForLayoutAdapterCallbackCount(2);
+
+ // Retry layout (which should succeed) as the layout call will stop canceling after the
+ // second time
+ clickRetryButton();
+
+ // Click the print button.
+ clickPrintButton();
+
+ // Answer the dialog for the print service cloud warning
+ answerPrintServicesWarning(true);
+
+ // Wait for the session to be destroyed to isolate tests.
+ waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
+ }
+
+ public void testUnexpectedWriteCancel() throws Exception {
+ if (!supportsPrinting()) {
+ return;
+ }
+ // Configure the print services.
+ FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+ SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+ final PrintAttributes[] printAttributes = new PrintAttributes[1];
+ final int[] numWriteCalls = new int[1];
+
+ // Create a mock print adapter.
+ final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+ new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+ LayoutResultCallback callback = (LayoutResultCallback) invocation.getArguments()[3];
+
+ callback.onLayoutFinished(
+ (new PrintDocumentInfo.Builder(PRINT_JOB_NAME)).build(), true);
+
+ // Mark layout was called.
+ onLayoutCalled();
+ return null;
+ }
+ }, new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ WriteResultCallback callback = (WriteResultCallback) args[3];
+
+ // Returned cancelled for the second write call which is unexpected
+ if (numWriteCalls[0] == 1) {
+ callback.onWriteCancelled();
+ } else {
+ PageRange[] pages = (PageRange[]) args[0];
+ ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
+ writeBlankPages(printAttributes[0], fd, 0, 1);
+ fd.close();
+ callback.onWriteFinished(pages);
+ }
+ numWriteCalls[0]++;
+
+ // Mark write was called.
+ onWriteCalled();
+ return null;
+ }
+ }, new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ // Mark finish was called.
+ onFinishCalled();
+ return null;
+ }
+ });
+
+ // Start printing.
+ print(adapter);
+
+ waitForWriteAdapterCallback(1);
+
+ // Select the second printer.
+ selectPrinter("Second printer");
+
+ // Wait for layout.
+ waitForWriteAdapterCallback(2);
+
+ // Retry write (which should succeed) as the write call will stop canceling after the
+ // second time
+ clickRetryButton();
+
+ // Click the print button.
+ clickPrintButton();
+
+ // Answer the dialog for the print service cloud warning
+ answerPrintServicesWarning(true);
+
+ // Wait for the session to be destroyed to isolate tests.
+ waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
+ }
+
public void testRequestedPagesNotWritten() throws Exception {
if (!supportsPrinting()) {
return;
@@ -1424,7 +1589,7 @@
// there are other printers but none of them was used.
PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.NA_LETTER)
+ .setMediaSize(getDefaultMediaSize())
.setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
.setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
.setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -1496,7 +1661,7 @@
// there are other printers but none of them was used.
PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.NA_LETTER)
+ .setMediaSize(getDefaultMediaSize())
.setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
.setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
.setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -1576,7 +1741,7 @@
// there are other printers but none of them was used.
PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
- .setMediaSize(MediaSize.NA_LETTER)
+ .setMediaSize(getDefaultMediaSize())
.setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
.setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
.setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
@@ -1595,6 +1760,189 @@
verifyNoMoreInteractions(adapter);
}
+ public void testLayoutCallbackCalledTwice() throws Exception {
+ if (!supportsPrinting()) {
+ return;
+ }
+ // Configure the print services.
+ FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+ SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+ // Create a mock print adapter.
+ final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+ new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+ .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+ .setPageCount(1)
+ .build();
+ LayoutResultCallback callback = (LayoutResultCallback) invocation
+ .getArguments()[3];
+
+ // Break the contract and call the callback twice.
+ callback.onLayoutFinished(info, true);
+ callback.onLayoutFinished(info, true);
+
+ // Mark layout called.
+ onLayoutCalled();
+ return null;
+ }
+ }, null, new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ // Mark finish was called.
+ onFinishCalled();
+ return null;
+ }
+ });
+
+ // Start printing.
+ print(adapter);
+
+ // Wait for layout.
+ waitForLayoutAdapterCallbackCount(1);
+
+ // Cancel printing.
+ getUiDevice().pressBack(); // wakes up the device.
+ getUiDevice().pressBack();
+
+ // Wait for a finish.
+ waitForAdapterFinishCallbackCalled();
+
+ // Wait for the session to be destroyed to isolate tests.
+ waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
+
+ // Verify the expected calls.
+ InOrder inOrder = inOrder(adapter);
+
+ // Start is always called first.
+ inOrder.verify(adapter).onStart();
+
+ // Start is always followed by a layout. The PDF printer is selected if
+ // there are other printers but none of them was used.
+ PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+ PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+ .setMediaSize(getDefaultMediaSize())
+ .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+ .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+ .setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
+ .build();
+ verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+ PageRange[] firstPage = new PageRange[] {new PageRange(0, 0)};
+ inOrder.verify(adapter).onWrite(eq(firstPage), any(ParcelFileDescriptor.class),
+ any(CancellationSignal.class), any(WriteResultCallback.class));
+
+ // Finish is always called last.
+ inOrder.verify(adapter).onFinish();
+
+ // No other call are expected.
+ verifyNoMoreInteractions(adapter);
+ }
+
+ public void testWriteCallbackCalledTwice() throws Exception {
+ if (!supportsPrinting()) {
+ return;
+ }
+ // Configure the print services.
+ FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+ SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+ final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+ // Create a mock print adapter.
+ final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+ new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+ PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+ .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+ .setPageCount(1)
+ .build();
+ LayoutResultCallback callback = (LayoutResultCallback) invocation
+ .getArguments()[3];
+
+ callback.onLayoutFinished(info, true);
+
+ // Mark layout called.
+ onLayoutCalled();
+ return null;
+ }
+ }, new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ PageRange[] pages = (PageRange[]) args[0];
+ ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
+ WriteResultCallback callback = (WriteResultCallback) args[3];
+
+ // Write only one pages
+ writeBlankPages(printAttributes[0], fd, 0, 0);
+ fd.close();
+
+ // Break the contract and call callback twice
+ callback.onWriteFinished(pages);
+ callback.onWriteFinished(pages);
+
+ // Mark write called
+ onWriteCalled();
+ return null;
+ }
+ }, new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ // Mark finish was called.
+ onFinishCalled();
+ return null;
+ }
+ });
+
+ // Start printing.
+ print(adapter);
+
+ // Wait for layout.
+ waitForLayoutAdapterCallbackCount(1);
+
+ // Cancel printing.
+ getUiDevice().pressBack(); // wakes up the device.
+ getUiDevice().pressBack();
+
+ // Wait for a finish.
+ waitForAdapterFinishCallbackCalled();
+
+ // Wait for the session to be destroyed to isolate tests.
+ waitForPrinterDiscoverySessionDestroyCallbackCalled(1);
+
+ // Verify the expected calls.
+ InOrder inOrder = inOrder(adapter);
+
+ // Start is always called first.
+ inOrder.verify(adapter).onStart();
+
+ // Start is always followed by a layout. The PDF printer is selected if
+ // there are other printers but none of them was used.
+ PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+ PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+ .setMediaSize(getDefaultMediaSize())
+ .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+ .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+ .setDuplexMode(PrintAttributes.DUPLEX_MODE_NONE)
+ .build();
+ verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+ PageRange[] firstPage = new PageRange[] {new PageRange(0, 0)};
+ inOrder.verify(adapter).onWrite(eq(firstPage), any(ParcelFileDescriptor.class),
+ any(CancellationSignal.class), any(WriteResultCallback.class));
+
+ // Finish is always called last.
+ inOrder.verify(adapter).onFinish();
+
+ // No other call are expected.
+ verifyNoMoreInteractions(adapter);
+ }
+
/**
* Pretend to have written two pages, but only actually write one page
*
@@ -1832,7 +2180,7 @@
PrinterCapabilitiesInfo firstCapabilities =
new PrinterCapabilitiesInfo.Builder(firstPrinterId)
.setMinMargins(new Margins(200, 200, 200, 200))
- .addMediaSize(MediaSize.ISO_A4, true)
+ .addMediaSize(MediaSize.ISO_A0, true)
.addMediaSize(MediaSize.ISO_A5, false)
.addResolution(new Resolution("300x300", "300x300", 300, 300), true)
.setColorModes(PrintAttributes.COLOR_MODE_COLOR,
@@ -1849,7 +2197,7 @@
PrinterCapabilitiesInfo secondCapabilities =
new PrinterCapabilitiesInfo.Builder(secondPrinterId)
.addMediaSize(MediaSize.ISO_A3, true)
- .addMediaSize(MediaSize.ISO_A4, false)
+ .addMediaSize(MediaSize.ISO_A0, false)
.addResolution(new Resolution("200x200", "200x200", 200, 200), true)
.addResolution(new Resolution("300x300", "300x300", 300, 300), false)
.setColorModes(PrintAttributes.COLOR_MODE_COLOR
@@ -1870,12 +2218,17 @@
// Add the third printer.
PrinterId thirdPrinterId = service.generatePrinterId("third_printer");
PrinterCapabilitiesInfo thirdCapabilities =
- new PrinterCapabilitiesInfo.Builder(thirdPrinterId)
- .addMediaSize(MediaSize.NA_LETTER, true)
- .addResolution(new Resolution("300x300", "300x300", 300, 300), true)
- .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
- PrintAttributes.COLOR_MODE_COLOR)
- .build();
+ null;
+ try {
+ thirdCapabilities = new PrinterCapabilitiesInfo.Builder(thirdPrinterId)
+ .addMediaSize(getDefaultMediaSize(), true)
+ .addResolution(new Resolution("300x300", "300x300", 300, 300), true)
+ .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
+ PrintAttributes.COLOR_MODE_COLOR)
+ .build();
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Cannot create third printer", e);
+ }
PrinterInfo thirdPrinter = new PrinterInfo.Builder(thirdPrinterId,
"Third printer", PrinterInfo.STATUS_IDLE)
.setCapabilities(thirdCapabilities)
diff --git a/tests/tests/print/src/android/print/cts/PrintJobTest.java b/tests/tests/print/src/android/print/cts/PrintJobTest.java
index b0f3742e..fc099ce 100644
--- a/tests/tests/print/src/android/print/cts/PrintJobTest.java
+++ b/tests/tests/print/src/android/print/cts/PrintJobTest.java
@@ -37,8 +37,6 @@
import android.print.cts.services.SecondPrintService;
import android.print.cts.services.StubbablePrinterDiscoverySession;
import android.printservice.PrintJob;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiSelector;
import android.util.Log;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -208,35 +206,6 @@
}
/**
- * Make sure that a runnable eventually finishes without throwing a exception.
- *
- * @param r The runnable to run.
- */
- private static void eventually(Runnable r) {
- final long TIMEOUT_MILLS = 5000;
- long start = System.currentTimeMillis();
-
- while (true) {
- try {
- r.run();
- break;
- } catch (Exception e) {
- if (System.currentTimeMillis() - start < TIMEOUT_MILLS) {
- Log.e(LOG_TAG, "Ignoring exception as we know that the print spooler does " +
- "not guarantee to process commands in order", e);
- try {
- Thread.sleep(100);
- } catch (InterruptedException e1) {
- Log.e(LOG_TAG, "Interrupted", e);
- }
- } else {
- throw e;
- }
- }
- }
- }
-
- /**
* Base test for the print job tests. Starts a print job and executes a testFn once the job is
* queued.
*
diff --git a/tests/tests/print/src/android/print/cts/PrinterCapabilitiesTest.java b/tests/tests/print/src/android/print/cts/PrinterCapabilitiesTest.java
index 8e3f984..91f9610 100644
--- a/tests/tests/print/src/android/print/cts/PrinterCapabilitiesTest.java
+++ b/tests/tests/print/src/android/print/cts/PrinterCapabilitiesTest.java
@@ -149,7 +149,8 @@
* @throws Exception If anything was unexpected.
*/
private void waitForPrinterUnavailable() throws Exception {
- final String PRINTER_UNAVAILABLE_MSG = "This printer isn't available right now.";
+ final String PRINTER_UNAVAILABLE_MSG =
+ getPrintSpoolerString("print_error_printer_unavailable");
UiObject message = getUiDevice().findObject(new UiSelector().resourceId(
"com.android.printspooler:id/message"));
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java
index f8f610a..0c6f411 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java
@@ -29,6 +29,7 @@
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Directory;
import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
import android.provider.cts.ContactsContract_TestDataBuilder.TestRawContact;
import android.provider.cts.contacts.ContactUtil;
@@ -228,6 +229,15 @@
new long[]{contact.getId()}
);
+ // Contacts.CONTENT_FILTER_URI
+ DatabaseAsserts.checkProjection(mResolver,
+ Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon().appendEncodedPath("xxx")
+ .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(Directory.DEFAULT)).build(),
+ PROJECTION,
+ new long[]{contact.getId()}
+ );
+
// Contacts.CONTENT_LOOKUP_URI
DatabaseAsserts.checkProjection(mResolver,
Contacts.getLookupUri(contactId, lookupKey),
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_DataTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_DataTest.java
index 33d3a28..62c6fdd 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_DataTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_DataTest.java
@@ -36,6 +36,7 @@
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Contacts.Entity;
import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.Directory;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.RawContactsEntity;
import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
@@ -533,6 +534,37 @@
assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[6]);
}
+ public void testEnterpriseCallableFilterByNameOrOrganization_returnsCorrectDataRows()
+ throws Exception {
+ long[] ids = setupContactablesTestData();
+ Uri uri = Uri.withAppendedPath(Callable.ENTERPRISE_CONTENT_FILTER_URI, "doe").buildUpon()
+ .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(Directory.DEFAULT))
+ .build();
+ // Only callables belonging to John Doe (name) and Cold Tamago (organization) are returned.
+ assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[5],
+ sContentValues[6]);
+ }
+
+ public void testEnterpriseCallableFilterByNumber_returnsCorrectDataRows() throws Exception {
+ long[] ids = setupContactablesTestData();
+ Uri uri = Uri.withAppendedPath(Callable.ENTERPRISE_CONTENT_FILTER_URI, "510").buildUpon()
+ .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(Directory.DEFAULT))
+ .build();
+ assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[1]);
+ }
+
+ public void testEnterpriseCallableFilterBySipAddress_returnsCorrectDataRows()
+ throws Exception {
+ long[] ids = setupContactablesTestData();
+ Uri uri = Uri.withAppendedPath(Callable.ENTERPRISE_CONTENT_FILTER_URI, "mysip").buildUpon()
+ .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(Directory.DEFAULT))
+ .build();
+ assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[6]);
+ }
+
public void testDataInsert_updatesContactLastUpdatedTimestamp() {
DatabaseAsserts.ContactIdPair ids = DatabaseAsserts.assertAndCreateContact(mResolver);
long baseTime = ContactUtil.queryContactLastUpdatedTimestamp(mResolver, ids.mContactId);
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_SearchSnippetsTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_SearchSnippetsTest.java
index 847e357..b049996 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_SearchSnippetsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_SearchSnippetsTest.java
@@ -28,6 +28,7 @@
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Directory;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.SearchSnippets;
import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
@@ -85,6 +86,15 @@
assertCursorStoredValuesWithContactsFilter(uri, ids);
}
+ public void testEnterpriseSearchSnippets_NoMatch() throws Exception {
+ long[] ids = setupTestData();
+ final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+ .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(Directory.DEFAULT)).appendPath("nomatch").build();
+
+ assertCursorStoredValuesWithContactsFilter(uri, ids);
+ }
+
public void testSearchSnippets_MatchEmailAddressCorrectSnippet() throws Exception {
long[] ids = setupTestData();
final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
@@ -96,6 +106,18 @@
assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
}
+ public void testEnterpriseSearchSnippets_MatchEmailAddressCorrectSnippet() throws Exception {
+ long[] ids = setupTestData();
+ final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+ .appendPath("farm").appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(Directory.DEFAULT)).build();
+
+ final ContentValues expected = new ContentValues();
+ expected.put(Contacts._ID, ids[1]);
+ expected.put(SearchSnippets.SNIPPET, "eggs@[farmers].org");
+ assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+ }
+
public void testSearchSnippets_MatchPhoneNumberCorrectSnippet() throws Exception {
long[] ids = setupTestData();
final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
@@ -107,6 +129,18 @@
assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
}
+ public void testEnterpriseSearchSnippets_MatchPhoneNumberCorrectSnippet() throws Exception {
+ long[] ids = setupTestData();
+ final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+ .appendPath("510").appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(Directory.DEFAULT)).build();
+
+ final ContentValues expected = new ContentValues();
+ expected.put(Contacts._ID, ids[0]);
+ expected.put(SearchSnippets.SNIPPET, "[510-123-5769]");
+ assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+ }
+
public void testSearchSnippets_MatchPostalAddressCorrectSnippet() throws Exception {
long[] ids = setupTestData();
final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
@@ -118,6 +152,18 @@
assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
}
+ public void testEnterpriseSearchSnippets_MatchPostalAddressCorrectSnippet() throws Exception {
+ long[] ids = setupTestData();
+ final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+ .appendPath("street").appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(Directory.DEFAULT)).build();
+
+ final ContentValues expected = new ContentValues();
+ expected.put(Contacts._ID, ids[2]);
+ expected.put(SearchSnippets.SNIPPET, "123 Main [Street] Unit 3113\u2026");
+ assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+ }
+
public void testSearchSnippets_LongMatchTruncation() throws Exception {
long[] ids = setupTestData();
final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
@@ -129,6 +175,18 @@
assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
}
+ public void testEnterpriseSearchSnippets_LongMatchTruncation() throws Exception {
+ long[] ids = setupTestData();
+ final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+ .appendPath("over").appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(Directory.DEFAULT)).build();
+
+ final ContentValues expected = new ContentValues();
+ expected.put(Contacts._ID, ids[2]);
+ expected.put(SearchSnippets.SNIPPET, "\u2026dog jumps [over] the quick\u2026");
+ assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+ }
+
public void testSearchSnippets_MultipleMatchesCorrectSnippet() throws Exception {
long[] ids = setupTestData();
final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
@@ -145,6 +203,23 @@
assertCursorStoredValuesWithContactsFilter(uri, ids, expected, expected2);
}
+ public void testEnterpriseSearchSnippets_MultipleMatchesCorrectSnippet() throws Exception {
+ long[] ids = setupTestData();
+ final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+ .appendPath("123").appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(Directory.DEFAULT)).build();
+
+ final ContentValues expected = new ContentValues();
+ expected.put(Contacts._ID, ids[1]);
+ expected.put(SearchSnippets.SNIPPET, "[123-456-7890]");
+
+ final ContentValues expected2 = new ContentValues();
+ expected2.put(Contacts._ID, ids[2]);
+ expected2.put(SearchSnippets.SNIPPET, "[123] Main Street Unit 3113\u2026");
+
+ assertCursorStoredValuesWithContactsFilter(uri, ids, expected, expected2);
+ }
+
/**
* Tests that if deferred snippeting is indicated, the provider will not perform formatting
* of the snippet for a single word query.
@@ -163,6 +238,25 @@
}
/**
+ * Tests that if deferred snippeting is indicated, the provider will not perform formatting
+ * of the snippet for a single word query.
+ */
+ public void testEnterpriseSearchSnippets_DeferredSnippetingSingleWordQuerySnippetDeferred()
+ throws Exception {
+ long[] ids = setupTestData();
+ final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+ .appendQueryParameter(SearchSnippets.DEFERRED_SNIPPETING_KEY, "1")
+ .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(Directory.DEFAULT))
+ .appendPath("510").build();
+
+ final ContentValues expected = new ContentValues();
+ expected.put(Contacts._ID, ids[0]);
+ expected.put(SearchSnippets.SNIPPET, "510-123-5769");
+ assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+ }
+
+ /**
* Tests that even if deferred snippeting is indicated, a multi-word query will have formatting
* of the snippet done by the provider using SQLite
*/
@@ -180,6 +274,25 @@
}
/**
+ * Tests that even if deferred snippeting is indicated, a multi-word query will have formatting
+ * of the snippet done by the provider using SQLite
+ */
+ public void testEnterpriseSearchSnippets_DeferredSnippetingMultiWordQuerySnippetNotDeferred()
+ throws Exception {
+ long[] ids = setupTestData();
+ final Uri uri = ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+ .appendQueryParameter(SearchSnippets.DEFERRED_SNIPPETING_KEY, "1")
+ .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(Directory.DEFAULT))
+ .appendPath("jumps over").build();
+
+ final ContentValues expected = new ContentValues();
+ expected.put(Contacts._ID, ids[2]);
+ expected.put(SearchSnippets.SNIPPET, "\u2026lazy dog [jumps] [over] the\u2026");
+ assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+ }
+
+ /**
* Given a uri, performs a query on the contacts provider for that uri and asserts that the
* cursor returned from the query matches the expected results.
*
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs b/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
index d731561..173c3ea 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
@@ -428,8 +428,32 @@
/////////////////////////////////////////////////////////////////////////
// Test out-of-range result.
+
+// When a result is ulong, it can take on values not representable on
+// the Java side, where there are no unsigned integral types and long
+// is the largest integral type -- i.e., all values in the range
+// (MAX_LONG, MAX_ULONG] are not representable in Java. The reflected
+// result_*.get() methods throw an exception if the result value is
+// out of range. The globals and reduction kernels below allow a test
+// case on the Java side to describe what kind of result we should
+// produce -- in particular, what to use for an in-range value and an
+// out-of-range value, and where (if anywhere) to put an out-of-range
+// value within the result (which might be scalar, vector, array of
+// scalar, or array of vector).
+
// We don't care about the input at all.
// We use these globals to configure the generation of the result.
+// A kernel puts 2*oorrBadResultHalf in the position (if any) of the result
+// given by oorrBadResult, and oorrGoodResult everywhere else.
+// The oorrBadPos encoding is as follows:
+// - For scalar result, 0 = scalar; anything else = nowhere
+// - For vector result, 0..length(vector)-1 = corresponding vector component
+// (0 = x, 1 = y, 2 = z, 3 = w); anything else = nowhere
+// - For array of scalar result, 0..length(array)-1 = corresponding array element;
+// anything else = nowhere
+// - For array of vector result, 0..length(vector)*length(array)-1 = corresponding
+// vector component C of corresponding array element E; anything else = nowhere
+// (encoding is C + length(vector)*E)
ulong oorrGoodResult; // the value of a good result
ulong oorrBadResultHalf; // half the value of a bad result
// ("half" because Java can only set the global from long not from ulong)
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index 7a67b08..1423aca 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -37,6 +37,14 @@
<service android:name="android.security.cts.activity.SecureRandomService"
android:process=":secureRandom"/>
+ <activity
+ android:name="android.security.cts.DisplayDriverActivity"
+ android:label="Test qhwc::MDPCompLowRes::allocLayerPipes (Qualcomm)">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+ </intent-filter>
+ </activity>
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/security/res/layout/activity_displaydriver.xml b/tests/tests/security/res/layout/activity_displaydriver.xml
new file mode 100755
index 0000000..9009dbf
--- /dev/null
+++ b/tests/tests/security/res/layout/activity_displaydriver.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:gravity="center"
+ android:orientation="vertical">
+
+ <VideoView
+ android:id="@+id/videoview"
+ android:layout_width="300dp"
+ android:layout_height="250dp"
+ android:layout_gravity="center"/>
+
+</LinearLayout>
+
+
+
+
diff --git a/tests/tests/security/res/raw/fuzz.webm b/tests/tests/security/res/raw/fuzz.webm
new file mode 100755
index 0000000..e5d95ce
--- /dev/null
+++ b/tests/tests/security/res/raw/fuzz.webm
Binary files differ
diff --git a/tests/app/app/src/android/app/stubs/ChildTabActivity.java b/tests/tests/security/src/android/security/cts/DisplayDriverActivity.java
old mode 100644
new mode 100755
similarity index 61%
rename from tests/app/app/src/android/app/stubs/ChildTabActivity.java
rename to tests/tests/security/src/android/security/cts/DisplayDriverActivity.java
index 1f0fb37..ca6c898
--- a/tests/app/app/src/android/app/stubs/ChildTabActivity.java
+++ b/tests/tests/security/src/android/security/cts/DisplayDriverActivity.java
@@ -1,25 +1,30 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-package android.app.stubs;
-
-import android.app.Activity;
-
-/**
- * An empty activity for the TabActivity test
- */
-public class ChildTabActivity extends Activity {
-}
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.security.cts;
+
+import android.security.cts.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class DisplayDriverActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_displaydriver);
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/DisplayDriverTest.java b/tests/tests/security/src/android/security/cts/DisplayDriverTest.java
new file mode 100755
index 0000000..7f3a0d4
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/DisplayDriverTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.security.cts;
+
+import android.security.cts.R;
+
+import android.app.Activity;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnErrorListener;
+import android.net.Uri;
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase2;
+import android.widget.MediaController;
+import android.widget.VideoView;
+
+public class DisplayDriverTest extends
+ ActivityInstrumentationTestCase2<DisplayDriverActivity> {
+ /**
+ * The maximum time to wait for an operation.
+ */
+ private static final int TIMEOUT_ASYNC_PROCESSING = 3000;
+ private Activity mActivity;
+
+ public DisplayDriverTest() {
+ super(DisplayDriverActivity.class);
+ }
+
+ /**
+ * Checks whether video crashed or not
+ * 1. Initializes mTriggered to false
+ * 2. sets mTriggered to true if onError() occurred while playing video
+ */
+ private static class MockListener {
+ private boolean mTriggered;
+
+ MockListener() {
+ mTriggered = false;
+ }
+
+ public boolean isTriggered() {
+ return mTriggered;
+ }
+
+ protected void onEvent() {
+ mTriggered = true;
+ }
+ }
+
+ private static class MockOnErrorListener extends MockListener implements
+ OnErrorListener {
+ public boolean onError(MediaPlayer mp, int what, int extra) {
+ super.onEvent();
+ return false;
+ }
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mActivity = getActivity();
+ assertNotNull("Failed to get the activity instance", mActivity);
+ }
+
+ /**
+ * 1. Runs the vulnerable video by registering OnErrorListener for VideoView
+ * 2. Wait for max time taken by video to crash and hit OnErrorListener
+ * 3. if video crashed - Pass the test case otherwise Fail the test case
+ */
+ public void testDisplayDriver_cve_2015_6634() {
+ final MockOnErrorListener listener = new MockOnErrorListener();
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ MediaController mMediaControls =
+ new MediaController(mActivity);
+ VideoView mVideoView =
+ (VideoView) mActivity.findViewById(R.id.videoview);
+ mVideoView.setMediaController(mMediaControls);
+ mVideoView.setOnErrorListener(listener);
+ mVideoView.setVideoURI(Uri.parse("android.resource://" +
+ mActivity.getPackageName() + "/" + R.raw.fuzz));
+ mVideoView.start();
+ } catch (Exception e) {
+ listener.onError(null, 0, 0);
+ }
+ }
+ });
+ SystemClock.sleep(TIMEOUT_ASYNC_PROCESSING);
+ assertTrue("Test case failed due to vulnerability in the video: " +
+ "Device is vulenrable to CVE-2015-6634", listener.isTriggered());
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (mActivity != null) {
+ mActivity.finish();
+ }
+ super.tearDown();
+ }
+}
diff --git a/tests/tests/speech/Android.mk b/tests/tests/speech/Android.mk
index 3d95053..68e0cba 100755
--- a/tests/tests/speech/Android.mk
+++ b/tests/tests/speech/Android.mk
@@ -21,7 +21,7 @@
# and when built explicitly put it in the data partition
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/systemui/Android.mk b/tests/tests/systemui/Android.mk
index 536d2a8..c31d825 100644
--- a/tests/tests/systemui/Android.mk
+++ b/tests/tests/systemui/Android.mk
@@ -26,7 +26,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/telecom/Android.mk b/tests/tests/telecom/Android.mk
index 5a8922e..27947af 100644
--- a/tests/tests/telecom/Android.mk
+++ b/tests/tests/telecom/Android.mk
@@ -24,7 +24,7 @@
# When built, explicitly put it in the data partition.
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/telephony/src/android/telephony/cts/SimRestrictedApisTest.java b/tests/tests/telephony/src/android/telephony/cts/SimRestrictedApisTest.java
index 0f09314..b15a4e8 100644
--- a/tests/tests/telephony/src/android/telephony/cts/SimRestrictedApisTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SimRestrictedApisTest.java
@@ -265,4 +265,20 @@
} catch (SecurityException expected) {
}
}
+
+ /**
+ * Tests the TelephonyManager.getIccAuthentication() API. This makes a call to
+ * getIccAuthentication() API and expects a SecurityException since the test apk is not
+ * signed by certificate on the SIM.
+ */
+ public void testGetIccAuthentication() {
+ try {
+ if (isSimCardPresent()) {
+ TelephonyManager.getDefault().getIccAuthentication(TelephonyManager.APPTYPE_USIM,
+ TelephonyManager.AUTHTYPE_EAP_AKA, "");
+ fail("Expected SecurityException. App doesn't have carrier privileges.");
+ }
+ } catch (SecurityException expected) {
+ }
+ }
}
diff --git a/tests/tests/text/Android.mk b/tests/tests/text/Android.mk
index 65a93fb..731fa9b 100644
--- a/tests/tests/text/Android.mk
+++ b/tests/tests/text/Android.mk
@@ -23,7 +23,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctsdeviceutillegacy ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctsdeviceutillegacy ctstestrunner android-support-test
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/text/AndroidManifest.xml b/tests/tests/text/AndroidManifest.xml
index fea237f..40a0b50 100644
--- a/tests/tests/text/AndroidManifest.xml
+++ b/tests/tests/text/AndroidManifest.xml
@@ -68,7 +68,7 @@
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- <data android:scheme="ctstest" />
+ <data android:scheme="ctstesttext" />
</intent-filter>
</activity>
diff --git a/tests/tests/text/res/values/strings.xml b/tests/tests/text/res/values/strings.xml
index c167278..b3db2a6 100644
--- a/tests/tests/text/res/values/strings.xml
+++ b/tests/tests/text/res/values/strings.xml
@@ -165,7 +165,7 @@
<string name="themes_prompt">Select a Theme:</string>
<string name="sample_text">Sample text goes here. I wanted something creative and whimsical
but then I just got bored...</string>
- <string name="long_text">This is a really long string which exceeds the width of the view.
+ <string name="long_text">This is a really long string which exceeds the width of the view.
New devices have a much larger screen which actually enables long strings to be displayed
with no fading. I have made this string longer to fix this case. If you are correcting this
text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
@@ -176,4 +176,8 @@
text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
I think so, so how about double this string, like copy and paste! </string>
<string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
+ <plurals name="list_ellipsize_test">
+ <item quantity="one">one more</item>
+ <item quantity="other"><xliff:g id="number">%d</xliff:g> more</item>
+ </plurals>
</resources>
diff --git a/tests/tests/text/src/android/text/cts/BidiFormatterTest.java b/tests/tests/text/src/android/text/cts/BidiFormatterTest.java
index 3e5db4d..b7aec1b 100644
--- a/tests/tests/text/src/android/text/cts/BidiFormatterTest.java
+++ b/tests/tests/text/src/android/text/cts/BidiFormatterTest.java
@@ -16,9 +16,13 @@
package android.text.cts;
+import android.icu.util.ULocale;
import android.test.AndroidTestCase;
import android.text.BidiFormatter;
+import android.text.SpannableString;
+import android.text.Spanned;
import android.text.TextDirectionHeuristics;
+import android.text.style.RelativeSizeSpan;
import java.util.Locale;
@@ -233,4 +237,83 @@
LRE + HE + EN + HE + PDF,
RTL_FMT_EXIT_RESET.unicodeWrap(HE + EN + HE, TextDirectionHeuristics.LTR, false));
}
+
+ public void testGetStereoReset() {
+ assertTrue(LTR_FMT.getStereoReset());
+ assertTrue(RTL_FMT.getStereoReset());
+ assertFalse(LTR_FMT_EXIT_RESET.getStereoReset());
+ assertFalse(RTL_FMT_EXIT_RESET.getStereoReset());
+ }
+
+ public void testBuilder_construction() {
+ final BidiFormatter defaultFmt = new BidiFormatter.Builder().build();
+ // Test that the default locale and the BidiFormatter's locale have the same direction.
+ assertEquals(ULocale.getDefault().isRightToLeft(), defaultFmt.isRtlContext());
+
+ final BidiFormatter ltrFmt = new BidiFormatter.Builder(false).build();
+ assertFalse(ltrFmt.isRtlContext());
+
+ final BidiFormatter rtlFmt = new BidiFormatter.Builder(true).build();
+ assertTrue(rtlFmt.isRtlContext());
+
+ final BidiFormatter englishFmt = new BidiFormatter.Builder(Locale.ENGLISH).build();
+ assertFalse(englishFmt.isRtlContext());
+
+ final BidiFormatter arabicFmt =
+ new BidiFormatter.Builder(Locale.forLanguageTag("ar")).build();
+ assertTrue(arabicFmt.isRtlContext());
+ }
+
+ public void testBuilder_setTextDirectionHeuristic() {
+ final BidiFormatter defaultFmt = new BidiFormatter.Builder().build();
+ assertFalse(defaultFmt.isRtl(EN + HE + EN));
+
+ final BidiFormatter modifiedFmt = new BidiFormatter.Builder().setTextDirectionHeuristic(
+ TextDirectionHeuristics.ANYRTL_LTR).build();
+ assertTrue(modifiedFmt.isRtl(EN + HE + EN));
+ }
+
+ public void testCharSequenceApis() {
+ final CharSequence CS_HE = new SpannableString(HE);
+ assertEquals(true, BidiFormatter.getInstance(true).isRtl(CS_HE));
+
+ final SpannableString CS_EN_HE = new SpannableString(EN + HE);
+ final Object RELATIVE_SIZE_SPAN = new RelativeSizeSpan(1.2f);
+ CS_EN_HE.setSpan(RELATIVE_SIZE_SPAN, 0, EN.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+
+ Spanned wrapped;
+ Object[] spans;
+
+ wrapped = (Spanned) LTR_FMT.unicodeWrap(CS_EN_HE);
+ assertEquals(EN + HE + LRM, wrapped.toString());
+ spans = wrapped.getSpans(0, wrapped.length(), Object.class);
+ assertEquals(1, spans.length);
+ assertEquals(RELATIVE_SIZE_SPAN, spans[0]);
+ assertEquals(0, wrapped.getSpanStart(RELATIVE_SIZE_SPAN));
+ assertEquals(EN.length(), wrapped.getSpanEnd(RELATIVE_SIZE_SPAN));
+
+ wrapped = (Spanned) LTR_FMT.unicodeWrap(CS_EN_HE, TextDirectionHeuristics.LTR);
+ assertEquals(EN + HE + LRM, wrapped.toString());
+ spans = wrapped.getSpans(0, wrapped.length(), Object.class);
+ assertEquals(1, spans.length);
+ assertEquals(RELATIVE_SIZE_SPAN, spans[0]);
+ assertEquals(0, wrapped.getSpanStart(RELATIVE_SIZE_SPAN));
+ assertEquals(EN.length(), wrapped.getSpanEnd(RELATIVE_SIZE_SPAN));
+
+ wrapped = (Spanned) LTR_FMT.unicodeWrap(CS_EN_HE, false);
+ assertEquals(EN + HE, wrapped.toString());
+ spans = wrapped.getSpans(0, wrapped.length(), Object.class);
+ assertEquals(1, spans.length);
+ assertEquals(RELATIVE_SIZE_SPAN, spans[0]);
+ assertEquals(0, wrapped.getSpanStart(RELATIVE_SIZE_SPAN));
+ assertEquals(EN.length(), wrapped.getSpanEnd(RELATIVE_SIZE_SPAN));
+
+ wrapped = (Spanned) LTR_FMT.unicodeWrap(CS_EN_HE, TextDirectionHeuristics.LTR, false);
+ assertEquals(EN + HE, wrapped.toString());
+ spans = wrapped.getSpans(0, wrapped.length(), Object.class);
+ assertEquals(1, spans.length);
+ assertEquals(RELATIVE_SIZE_SPAN, spans[0]);
+ assertEquals(0, wrapped.getSpanStart(RELATIVE_SIZE_SPAN));
+ assertEquals(EN.length(), wrapped.getSpanEnd(RELATIVE_SIZE_SPAN));
+ }
}
diff --git a/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java b/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java
index 6dee5e9..09b5dbf 100644
--- a/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java
+++ b/tests/tests/text/src/android/text/cts/SpannableStringBuilderTest.java
@@ -21,19 +21,20 @@
import android.test.suitebuilder.annotation.SmallTest;
import android.text.Editable;
import android.text.InputFilter;
+import android.text.Selection;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextWatcher;
import android.text.style.BulletSpan;
-import android.text.style.ParagraphStyle;
import android.text.style.QuoteSpan;
-import android.text.style.RelativeSizeSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.SubscriptSpan;
import android.text.style.TabStopSpan;
import android.text.style.UnderlineSpan;
+import java.util.Arrays;
+
/**
* Test {@link SpannableStringBuilder}.
*/
@@ -377,6 +378,28 @@
}
}
+ @SmallTest
+ public void testAppend_textWithSpan() {
+ final QuoteSpan span = new QuoteSpan();
+ final SpannableStringBuilder builder = new SpannableStringBuilder("hello ");
+ final int spanStart = builder.length();
+ builder.append("planet", span, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ final int spanEnd = builder.length();
+ builder.append(" earth");
+
+ assertEquals("SpannableStringBuilder.append should append text to existing whole text",
+ "hello planet earth", builder.toString());
+
+ final Object[] spans = builder.getSpans(0, builder.length(), Object.class);
+ assertNotNull("Appended text included a Quote span", spans);
+ assertEquals("Appended text included a Quote span", 1, spans.length);
+ assertSame("Should be the same span instance", span, spans[0]);
+ assertEquals("Appended span should start at appended text start",
+ spanStart, builder.getSpanStart(spans[0]));
+ assertEquals("Appended span should end at appended text end",
+ spanEnd, builder.getSpanEnd(spans[0]));
+ }
+
public void testClearSpans() {
SpannableStringBuilder builder = new SpannableStringBuilder("hello, world");
@@ -688,6 +711,19 @@
assertEquals(0, builder.length());
}
+ public void testReplace_shouldNotThrowIndexOutOfBoundsExceptionForLongText() {
+ final char[] charArray = new char[75000];
+ Arrays.fill(charArray, 'a');
+ final String text = new String(charArray, 0, 50000);
+ final String copiedText = new String(charArray);
+ final SpannableStringBuilder spannable = new SpannableStringBuilder(text);
+ Selection.setSelection(spannable, text.length());
+
+ spannable.replace(0, text.length(), copiedText);
+
+ assertEquals(copiedText.length(), spannable.length());
+ }
+
public void testDelete() {
SpannableStringBuilder builder = new SpannableStringBuilder("hello,world");
assertEquals("hello,world", builder.toString());
diff --git a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
index ed3f1ea..f66f4c0 100644
--- a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
+++ b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
@@ -100,8 +100,6 @@
maxLines);
}
-
-
/**
* Constructor test
*/
@@ -523,37 +521,53 @@
TextUtils.TruncateAt.MARQUEE, 1);
assertTrue(layout.getEllipsisCount(0) == 0);
}
+ {
+ final String text = "\u3042" // HIRAGANA LETTER A
+ + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
+ final float textWidth = mDefaultPaint.measureText(text);
+ final int halfWidth = (int)(textWidth / 2.0f);
+ {
+ StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
+ halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
+ SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.END, halfWidth, 1);
+ assertTrue(layout.getEllipsisCount(0) > 0);
+ assertTrue(layout.getEllipsisStart(0) > 0);
+ }
+ {
+ StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
+ halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
+ SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.START, halfWidth, 1);
+ assertTrue(layout.getEllipsisCount(0) > 0);
+ assertEquals(0, mDefaultLayout.getEllipsisStart(0));
+ }
+ {
+ StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
+ halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
+ SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.MIDDLE, halfWidth, 1);
+ assertTrue(layout.getEllipsisCount(0) > 0);
+ assertTrue(layout.getEllipsisStart(0) > 0);
+ }
+ {
+ StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
+ halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
+ SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.MARQUEE, halfWidth, 1);
+ assertEquals(0, layout.getEllipsisCount(0));
+ }
+ }
- final String text = "\u3042" // HIRAGANA LETTER A
- + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
- final float textWidth = mDefaultPaint.measureText(text);
- final int halfWidth = (int)(textWidth / 2.0f);
{
- StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
- halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
- SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.END, halfWidth, 1);
- assertTrue(layout.getEllipsisCount(0) > 0);
- assertTrue(layout.getEllipsisStart(0) > 0);
- }
- {
- StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
- halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
- SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.START, halfWidth, 1);
- assertTrue(layout.getEllipsisCount(0) > 0);
- assertEquals(0, mDefaultLayout.getEllipsisStart(0));
- }
- {
- StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
- halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
- SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.MIDDLE, halfWidth, 1);
- assertTrue(layout.getEllipsisCount(0) > 0);
- assertTrue(layout.getEllipsisStart(0) > 0);
- }
- {
- StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
- halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
- SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.MARQUEE, halfWidth, 1);
- assertEquals(0, layout.getEllipsisCount(0));
+ // The white spaces in this text will be trailing if maxLines is larger than 1, but
+ // width of the trailing white spaces must not be ignored if ellipsis is applied.
+ final String text = "abc def";
+ final float textWidth = mDefaultPaint.measureText(text);
+ final int halfWidth = (int)(textWidth / 2.0f);
+ {
+ StaticLayout layout = new StaticLayout(text, 0, text.length(), mDefaultPaint,
+ halfWidth, DEFAULT_ALIGN, TextDirectionHeuristics.FIRSTSTRONG_LTR,
+ SPACE_MULTI, SPACE_ADD, false, TextUtils.TruncateAt.END, halfWidth, 1);
+ assertTrue(layout.getEllipsisCount(0) > 0);
+ assertTrue(layout.getEllipsisStart(0) > 0);
+ }
}
}
diff --git a/tests/tests/text/src/android/text/cts/TextUtilsTest.java b/tests/tests/text/src/android/text/cts/TextUtilsTest.java
index 0da1eb4..1b97c95 100644
--- a/tests/tests/text/src/android/text/cts/TextUtilsTest.java
+++ b/tests/tests/text/src/android/text/cts/TextUtilsTest.java
@@ -20,12 +20,16 @@
import static android.view.View.LAYOUT_DIRECTION_LTR;
import static android.view.View.LAYOUT_DIRECTION_RTL;
+import android.content.Context;
import android.content.res.ColorStateList;
+import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.Typeface;
+import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
import android.test.AndroidTestCase;
@@ -45,6 +49,8 @@
import android.util.StringBuilderPrinter;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;
@@ -80,6 +86,109 @@
return re.substring(0, re.indexOf("x"));
}
+ /**
+ * @return the number of times the code unit appears in the CharSequence.
+ */
+ private int countChars(CharSequence s, char c) {
+ int count = 0;
+ for (int i = 0; i < s.length(); i++) {
+ if (s.charAt(i) == c) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ public void testListEllipsize() {
+ final Context context = getContext();
+ final TextPaint paint = new TextPaint();
+ final int moreId = R.plurals.list_ellipsize_test; // "one more" for 1, "%d more" for other
+
+ final List fullList = Arrays.asList("A", "B", "C", "D", "E", "F", "G", "H", "I", "J");
+ final String separator = ", ";
+ final String fullString = TextUtils.join(separator, fullList);
+ final float fullWidth = paint.measureText(fullString);
+ assertEquals("",
+ TextUtils.listEllipsize(context, null, separator, paint, fullWidth, moreId));
+
+ final List<CharSequence> emptyList = new ArrayList<CharSequence>();
+ assertEquals("",
+ TextUtils.listEllipsize(context, emptyList, separator, paint, fullWidth, moreId));
+
+ // Null context should cause ellipsis to be used at the end.
+ final String ellipsizedWithNull = TextUtils.listEllipsize(
+ null, fullList, separator, paint, fullWidth / 2, 0).toString();
+ assertTrue(ellipsizedWithNull.endsWith(getEllipsis()));
+
+ // Test that the empty string gets returned if there's no space.
+ assertEquals("",
+ TextUtils.listEllipsize(context, fullList, separator, paint, 1.0f, moreId));
+
+ // Test that the full string itself can get returned if there's enough space.
+ assertEquals(fullString,
+ TextUtils.listEllipsize(context, fullList, separator, paint, fullWidth, moreId)
+ .toString());
+ assertEquals(fullString,
+ TextUtils.listEllipsize(context, fullList, separator, paint, fullWidth * 2,
+ moreId).toString());
+
+ final float epsilon = fullWidth / 20;
+ for (float width = epsilon; width < fullWidth - epsilon / 2; width += epsilon) {
+ final String ellipsized = TextUtils.listEllipsize(
+ context, fullList, separator, paint, width, moreId).toString();
+ // Since we don't have the full space, test that we are not getting the full string.
+ assertFalse(fullString.equals(ellipsized));
+
+ if (!ellipsized.isEmpty()) {
+ assertTrue(ellipsized.endsWith(" more"));
+ // Test that the number of separators (which equals the number of output elements),
+ // plus the number output before more always equals the number of original elements.
+ final int lastSpace = ellipsized.lastIndexOf(' ');
+ final int penultimateSpace = ellipsized.lastIndexOf(' ', lastSpace - 1);
+ assertEquals(',', ellipsized.charAt(penultimateSpace - 1));
+ final String moreCountString = ellipsized.substring(
+ penultimateSpace + 1, lastSpace);
+ final int moreCount = (moreCountString.equals("one"))
+ ? 1 : Integer.parseInt(moreCountString);
+ final int commaCount = countChars(ellipsized, ',');
+ assertEquals(fullList.size(), commaCount + moreCount);
+ }
+ }
+}
+
+ public void testListEllipsize_rtl() {
+ final Context context = getContext();
+ final Resources res = context.getResources();
+ final Configuration newConfig = new Configuration(res.getConfiguration());
+
+ // save the locales and set them to just Arabic
+ final LocaleList previousLocales = newConfig.getLocales();
+ newConfig.setLocales(LocaleList.forLanguageTags("ar"));
+ res.updateConfiguration(newConfig, null);
+
+ try {
+ final TextPaint paint = new TextPaint();
+ final int moreId = R.plurals.list_ellipsize_test; // "one more" for 1, else "%d more"
+ final String RLM = "\u200F";
+ final String LRE = "\u202A";
+ final String PDF = "\u202C";
+
+ final List fullList = Arrays.asList("A", "B");
+ final String separator = ", ";
+ final String expectedString =
+ RLM + LRE + "A" + PDF + RLM + ", " + RLM + LRE + "B" + PDF + RLM;
+ final float enoughWidth = paint.measureText(expectedString);
+
+ assertEquals(expectedString,
+ TextUtils.listEllipsize(context, fullList, separator, paint, enoughWidth,
+ moreId).toString());
+ } finally {
+ // Restore the original locales
+ newConfig.setLocales(previousLocales);
+ res.updateConfiguration(newConfig, null);
+ }
+ }
+
public void testCommaEllipsize() {
TextPaint p = new TextPaint();
String text = "long, string, to, truncate";
diff --git a/tests/tests/text/src/android/text/format/cts/FormatterTest.java b/tests/tests/text/src/android/text/format/cts/FormatterTest.java
index 6acfb84..5ae19e7 100644
--- a/tests/tests/text/src/android/text/format/cts/FormatterTest.java
+++ b/tests/tests/text/src/android/text/format/cts/FormatterTest.java
@@ -20,16 +20,18 @@
import java.math.MathContext;
import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
import android.text.format.Formatter;
public class FormatterTest extends AndroidTestCase {
+ @SmallTest
public void testFormatFileSize() {
// test null Context
assertEquals("", Formatter.formatFileSize(null, 0));
MathContext mc = MathContext.DECIMAL64;
- BigDecimal bd = new BigDecimal((long) 1024, mc);
+ BigDecimal bd = new BigDecimal((long) 1000, mc);
// test different long values with various length
assertEquals("0 B", Formatter.formatFileSize(mContext, 0));
@@ -39,9 +41,9 @@
assertEquals("99 B", Formatter.formatFileSize(mContext, 99));
assertEquals("100 B", Formatter.formatFileSize(mContext, 100));
assertEquals("900 B", Formatter.formatFileSize(mContext, 900));
- assertEquals("0.88 KB", Formatter.formatFileSize(mContext, 901));
+ assertEquals("0.90 kB", Formatter.formatFileSize(mContext, 901));
- assertEquals("1.00 KB", Formatter.formatFileSize(mContext, bd.pow(1).longValue()));
+ assertEquals("1.00 kB", Formatter.formatFileSize(mContext, bd.pow(1).longValue()));
assertEquals("1.00 MB", Formatter.formatFileSize(mContext, bd.pow(2).longValue()));
@@ -51,12 +53,13 @@
assertEquals("1.00 PB", Formatter.formatFileSize(mContext, bd.pow(5).longValue()));
- assertEquals("1024 PB", Formatter.formatFileSize(mContext, bd.pow(6).longValue()));
+ assertEquals("1000 PB", Formatter.formatFileSize(mContext, bd.pow(6).longValue()));
// test Negative value
assertEquals("-1 B", Formatter.formatFileSize(mContext, -1));
}
+ @SmallTest
public void testFormatIpAddress() {
assertEquals("1.0.168.192", Formatter.formatIpAddress(0xC0A80001));
assertEquals("1.0.0.127", Formatter.formatIpAddress(0x7F000001));
diff --git a/tests/tests/text/src/android/text/method/cts/BackspaceTest.java b/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
index 1705326..212d4eb 100644
--- a/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
+++ b/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
@@ -59,6 +59,31 @@
}
@SmallTest
+ public void testCRLF() {
+ EditorState state = new EditorState();
+
+ // U+000A is LINE FEED.
+ state.setByString("U+000A |");
+ backspace(state, 0);
+ state.assertEquals("|");
+
+ // U+000D is CARRIAGE RETURN.
+ state.setByString("U+000D |");
+ backspace(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("U+000D U+000A |");
+ backspace(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("U+000A U+000D |");
+ backspace(state, 0);
+ state.assertEquals("U+000A |");
+ backspace(state, 0);
+ state.assertEquals("|");
+ }
+
+ @SmallTest
public void testSurrogatePairs() {
EditorState state = new EditorState();
diff --git a/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java b/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
index 40ed593..3b226fb 100644
--- a/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
@@ -59,6 +59,30 @@
}
@SmallTest
+ public void testCRLF() {
+ EditorState state = new EditorState();
+
+ // U+000A is LINE FEED.
+ state.setByString("| U+000A");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // U+000D is CARRIAGE RETURN.
+ state.setByString("| U+000D");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+000D U+000A");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+000A U+000D");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+000D");
+ forwardDelete(state, 0);
+ }
+
+ @SmallTest
public void testSurrogatePairs() {
EditorState state = new EditorState();
diff --git a/tests/tests/text/src/android/text/style/cts/SuggestionSpanTest.java b/tests/tests/text/src/android/text/style/cts/SuggestionSpanTest.java
index ff5167c..ef883b1 100644
--- a/tests/tests/text/src/android/text/style/cts/SuggestionSpanTest.java
+++ b/tests/tests/text/src/android/text/style/cts/SuggestionSpanTest.java
@@ -21,12 +21,111 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
import android.text.style.SuggestionSpan;
import java.util.Locale;
+import static org.junit.Assert.assertArrayEquals;
+
public class SuggestionSpanTest extends TestCase {
+ @SmallTest
+ public void testGetSuggestionSpans() {
+ final String[] suggestions = new String[]{"suggestion1", "suggestion2"};
+ final SuggestionSpan span = new SuggestionSpan(Locale.forLanguageTag("en"), suggestions,
+ SuggestionSpan.FLAG_AUTO_CORRECTION);
+ assertArrayEquals("Should return the correct suggestions array",
+ suggestions, span.getSuggestions());
+
+ final SuggestionSpan clonedSpan = cloneViaParcel(span);
+ assertArrayEquals("Should (de)serialize suggestions",
+ suggestions, clonedSpan.getSuggestions());
+ }
+
+ @SmallTest
+ public void testGetSuggestionSpans_emptySuggestions() {
+ final String[] suggestions = new String[0];
+ final SuggestionSpan span = new SuggestionSpan(Locale.forLanguageTag("en"), suggestions,
+ SuggestionSpan.FLAG_AUTO_CORRECTION);
+ assertArrayEquals("Span should return empty suggestion array",
+ suggestions, span.getSuggestions());
+
+ // also test parceling
+ final SuggestionSpan clonedSpan = cloneViaParcel(span);
+ assertArrayEquals("Should (de)serialize empty suggestions array",
+ suggestions, clonedSpan.getSuggestions());
+ }
+
+ @SmallTest
+ public void testGetSuggestionSpans_suggestionsWithNullValue() {
+ final String[] suggestions = new String[]{"suggestion", null};
+ final SuggestionSpan span = new SuggestionSpan(Locale.forLanguageTag("en"), suggestions,
+ SuggestionSpan.FLAG_AUTO_CORRECTION);
+ assertArrayEquals("Should accept and return null suggestions",
+ suggestions, span.getSuggestions());
+
+ final SuggestionSpan clonedSpan = cloneViaParcel(span);
+ assertArrayEquals("Should (de)serialize null in suggestions array",
+ suggestions, clonedSpan.getSuggestions());
+ }
+
+ @SmallTest
+ public void testGetFlags() {
+ final String[] anySuggestions = new String[0];
+ final int flag = SuggestionSpan.FLAG_AUTO_CORRECTION;
+ SuggestionSpan span = new SuggestionSpan(Locale.forLanguageTag("en"), anySuggestions, flag);
+
+ assertEquals("Should return the flag passed in constructor",
+ flag, span.getFlags());
+
+ final SuggestionSpan clonedSpan = cloneViaParcel(span);
+ assertEquals("Should (de)serialize flags", flag, clonedSpan.getFlags());
+ }
+
+ @SmallTest
+ public void testEquals_returnsTrueForDeserializedInstances() {
+ final SuggestionSpan span1 = new SuggestionSpan(null, Locale.forLanguageTag("en"),
+ new String[0], SuggestionSpan.FLAG_AUTO_CORRECTION, SuggestionSpan.class);
+ final SuggestionSpan span2 = cloneViaParcel(span1);
+
+ assertTrue("(De)serialized instances should be equal", span1.equals(span2));
+ }
+
+ @SmallTest
+ public void testEquals_returnsTrueIfTheFlagsAreDifferent() {
+ final SuggestionSpan span1 = new SuggestionSpan(null, Locale.forLanguageTag("en"),
+ new String[0], SuggestionSpan.FLAG_AUTO_CORRECTION, SuggestionSpan.class);
+ final SuggestionSpan span2 = cloneViaParcel(span1);
+ span2.setFlags(SuggestionSpan.FLAG_EASY_CORRECT);
+
+ assertEquals("Should return the flag passed in set function",
+ SuggestionSpan.FLAG_EASY_CORRECT, span2.getFlags());
+
+ assertTrue("Instances with different flags should be equal", span1.equals(span2));
+ }
+
+ @SmallTest
+ public void testEquals_returnsFalseIfCreationTimeIsNotSame() {
+ final Locale anyLocale = Locale.forLanguageTag("en");
+ final String[] anySuggestions = new String[0];
+ final int anyFlags = SuggestionSpan.FLAG_AUTO_CORRECTION;
+ final Class anyClass = SuggestionSpan.class;
+
+ final SuggestionSpan span1 = new SuggestionSpan(null, anyLocale, anySuggestions, anyFlags,
+ anyClass);
+ try {
+ // let some time pass before constructing the other span
+ Thread.sleep(2);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ final SuggestionSpan span2 = new SuggestionSpan(null, anyLocale, anySuggestions, anyFlags,
+ anyClass);
+
+ assertFalse("Instances created at different time should not be equal", span2.equals(span1));
+ }
+
/**
* @param locale a {@link Locale} object.
* @return A well-formed BCP 47 language tag representation.
@@ -62,6 +161,7 @@
assertEquals(getNonNullLocaleString(locale), cloned.getLocale());
}
+ @SmallTest
public void testGetLocaleObject() {
checkGetLocaleObject(Locale.forLanguageTag("en"));
checkGetLocaleObject(Locale.forLanguageTag("en-GB"));
diff --git a/tests/tests/text/src/android/text/style/cts/URLSpanTest.java b/tests/tests/text/src/android/text/style/cts/URLSpanTest.java
index 330db77..e5ccf59 100644
--- a/tests/tests/text/src/android/text/style/cts/URLSpanTest.java
+++ b/tests/tests/text/src/android/text/style/cts/URLSpanTest.java
@@ -28,8 +28,8 @@
import android.widget.TextView;
public class URLSpanTest extends ActivityInstrumentationTestCase2<URLSpanCtsActivity> {
- // The scheme of TEST_URL must be "ctstest" to launch MockURLSpanTestActivity
- private static final String TEST_URL = "ctstest://urlSpan/test";
+ // The scheme of TEST_URL must be "ctstesttext" to launch MockURLSpanTestActivity
+ private static final String TEST_URL = "ctstesttext://urlSpan/test";
private Activity mActivity;
public URLSpanTest() {
diff --git a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
index a159da9..431c754 100644
--- a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
+++ b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
@@ -592,13 +592,6 @@
}
@SmallTest
- public void testAddLinks_partiallyMatchesUrlWithInvalidRequestParameter() throws Exception {
- String url = "http://android.com?p=value";
- assertAddLinksWithWebUrlPartiallyMatches("Should partially match URL with invalid " +
- "request parameter", "http://android.com", url);
- }
-
- @SmallTest
public void testAddLinks_matchesValidUrlWithEmoji() throws Exception {
String url = "Thank\u263A.com";
assertAddLinksWithWebUrlSucceeds("Should match URL with emoji", url);
@@ -669,6 +662,48 @@
}
}
+ @SmallTest
+ public void testAddLinks_matchesDomainNameWithDash() throws Exception {
+ String url = "http://a-nd.r-oid.com";
+ assertAddLinksWithWebUrlSucceeds("Should match domain name with '-'", url);
+
+ url = "a-nd.r-oid.com";
+ assertAddLinksWithWebUrlSucceeds("Should match domain name with '-'", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesDomainNameWithUnderscore() throws Exception {
+ String url = "http://a_nd.r_oid.com";
+ assertAddLinksWithWebUrlSucceeds("Should match domain name with '_'", url);
+
+ url = "a_nd.r_oid.com";
+ assertAddLinksWithWebUrlSucceeds("Should match domain name with '_'", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesPathAndQueryWithDollarSign() throws Exception {
+ String url = "http://android.com/path$?v=$val";
+ assertAddLinksWithWebUrlSucceeds("Should match path and query with '$'", url);
+
+ url = "android.com/path$?v=$val";
+ assertAddLinksWithWebUrlSucceeds("Should match path and query with '$'", url);
+ }
+
+ @SmallTest
+ public void testAddLinks_matchesEmptyPathWithQueryParams() throws Exception {
+ String url = "http://android.com?q=v";
+ assertAddLinksWithWebUrlSucceeds("Should match empty path with query params", url);
+
+ url = "android.com?q=v";
+ assertAddLinksWithWebUrlSucceeds("Should match empty path with query params", url);
+
+ url = "http://android.com/?q=v";
+ assertAddLinksWithWebUrlSucceeds("Should match empty path with query params", url);
+
+ url = "android.com/?q=v";
+ assertAddLinksWithWebUrlSucceeds("Should match empty path with query params", url);
+ }
+
// EMAIL_ADDRESSES Related Tests
public void testAddLinks_email_matchesShortValidEmail() throws Exception {
diff --git a/tests/tests/text/src/android/text/util/cts/Rfc822TokenizerTest.java b/tests/tests/text/src/android/text/util/cts/Rfc822TokenizerTest.java
index 4d145f1..b3aa714 100644
--- a/tests/tests/text/src/android/text/util/cts/Rfc822TokenizerTest.java
+++ b/tests/tests/text/src/android/text/util/cts/Rfc822TokenizerTest.java
@@ -18,17 +18,24 @@
import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
import android.text.util.Rfc822Token;
import android.text.util.Rfc822Tokenizer;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Test {@link Rfc822Tokenizer}.
*/
public class Rfc822TokenizerTest extends AndroidTestCase {
+
+ @SmallTest
public void testConstructor() {
new Rfc822Tokenizer();
}
+ @SmallTest
public void testFindTokenStart() {
Rfc822Tokenizer rfc822Tokenizer = new Rfc822Tokenizer();
@@ -61,6 +68,7 @@
}
}
+ @SmallTest
public void testFindTokenEnd() {
Rfc822Tokenizer rfc822Tokenizer = new Rfc822Tokenizer();
@@ -96,6 +104,7 @@
}
}
+ @SmallTest
public void testTerminateToken() {
Rfc822Tokenizer rfc822Tokenizer = new Rfc822Tokenizer();
@@ -110,21 +119,22 @@
assertEquals(text + comma + space, rfc822Tokenizer.terminateToken(null));
}
+ @SmallTest
public void testTokenize() {
Rfc822Token[] tokens = Rfc822Tokenizer.tokenize("");
assertEquals(0, tokens.length);
- String text = "\"Berg\" (home) <berg\\@google.com>, tom\\@google.com (work)";
+ String text = "\"Berg\" (home) <berg\\@example.com>, tom\\@example.com (work)";
tokens = Rfc822Tokenizer.tokenize(text);
assertEquals(2, tokens.length);
- localAssertEquals(tokens[0], "Berg", "berg\\@google.com", "home");
- localAssertEquals(tokens[1], null, "tom\\@google.com", "work");
+ localAssertEquals(tokens[0], "Berg", "berg\\@example.com", "home");
+ localAssertEquals(tokens[1], null, "tom\\@example.com", "work");
- text = "Foo Bar (something) <foo\\@google.com>, blah\\@google.com (something)";
+ text = "Foo Bar (something) <foo\\@example.com>, blah\\@example.com (something)";
tokens = Rfc822Tokenizer.tokenize(text);
assertEquals(2, tokens.length);
- localAssertEquals(tokens[0], "Foo Bar", "foo\\@google.com", "something");
- localAssertEquals(tokens[1], null, "blah\\@google.com", "something");
+ localAssertEquals(tokens[0], "Foo Bar", "foo\\@example.com", "something");
+ localAssertEquals(tokens[1], null, "blah\\@example.com", "something");
try {
Rfc822Tokenizer.tokenize(null);
@@ -134,6 +144,32 @@
}
}
+ @SmallTest
+ public void testTokenize_withListParam() {
+ final List<Rfc822Token> list = new ArrayList<>();
+ Rfc822Tokenizer.tokenize("", list);
+ assertEquals(0, list.size());
+
+ String text = "\"Berg\" (home) <berg\\@example.com>, tom\\@example.com (work)";
+ Rfc822Tokenizer.tokenize(text, list);
+ assertEquals(2, list.size());
+ localAssertEquals(list.get(0), "Berg", "berg\\@example.com", "home");
+ localAssertEquals(list.get(1), null, "tom\\@example.com", "work");
+
+ text = "Foo Bar (something) <foo\\@example.com>, blah\\@example.com (something)";
+ list.clear();
+ Rfc822Tokenizer.tokenize(text, list);
+ assertEquals(2, list.size());
+ localAssertEquals(list.get(0), "Foo Bar", "foo\\@example.com", "something");
+ localAssertEquals(list.get(1), null, "blah\\@example.com", "something");
+
+ try {
+ Rfc822Tokenizer.tokenize(null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ }
+ }
+
/**
* Assert the specified token's name, address and comment all equal specified ones.
* @param token the Rfc822Token to be asserted.
diff --git a/tests/tests/transition/Android.mk b/tests/tests/transition/Android.mk
index af8b4eb..5370d4f 100644
--- a/tests/tests/transition/Android.mk
+++ b/tests/tests/transition/Android.mk
@@ -24,13 +24,19 @@
# When built, explicitly put it in the data partition.
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES += \
+ android-support-test \
+ mockito-target \
+ android-common \
+ ctsdeviceutil \
+ ctstestrunner \
+ platform-test-annotations
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_SRC_FILES := $(call all-java-files-under, src)
# Tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts
-LOCAL_SDK_VERSION := current
-
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/transition/res/layout/scene11.xml b/tests/tests/transition/res/layout/scene11.xml
new file mode 100644
index 0000000..8ecad8d
--- /dev/null
+++ b/tests/tests/transition/res/layout/scene11.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:transitionName="holder"
+ android:id="@+id/holder">
+ <ImageView
+ android:id="@+id/redSquare"
+ android:src="#F00"
+ android:layout_width="10dp"
+ android:layout_height="10dp"/>
+</RelativeLayout>
diff --git a/tests/tests/transition/res/transition/arc_motion.xml b/tests/tests/transition/res/transition/arc_motion.xml
new file mode 100644
index 0000000..264f074
--- /dev/null
+++ b/tests/tests/transition/res/transition/arc_motion.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android">
+ <arcMotion android:minimumVerticalAngle="1"
+ android:minimumHorizontalAngle="2"
+ android:maximumAngle="53"/>
+</changeBounds>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/auto_transition.xml b/tests/tests/transition/res/transition/auto_transition.xml
new file mode 100644
index 0000000..e285105
--- /dev/null
+++ b/tests/tests/transition/res/transition/auto_transition.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<autoTransition/>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/change_bounds.xml b/tests/tests/transition/res/transition/change_bounds.xml
new file mode 100644
index 0000000..162372c
--- /dev/null
+++ b/tests/tests/transition/res/transition/change_bounds.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android"
+ android:resizeClip="true"/>
diff --git a/tests/tests/transition/res/transition/change_clip_bounds.xml b/tests/tests/transition/res/transition/change_clip_bounds.xml
new file mode 100644
index 0000000..70a7dc6
--- /dev/null
+++ b/tests/tests/transition/res/transition/change_clip_bounds.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<changeClipBounds/>
diff --git a/tests/tests/transition/res/transition/change_image_transform.xml b/tests/tests/transition/res/transition/change_image_transform.xml
new file mode 100644
index 0000000..b37ab04
--- /dev/null
+++ b/tests/tests/transition/res/transition/change_image_transform.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<changeImageTransform/>
diff --git a/tests/tests/transition/res/transition/change_scroll.xml b/tests/tests/transition/res/transition/change_scroll.xml
new file mode 100644
index 0000000..9054686
--- /dev/null
+++ b/tests/tests/transition/res/transition/change_scroll.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<changeScroll/>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/change_transform.xml b/tests/tests/transition/res/transition/change_transform.xml
new file mode 100644
index 0000000..c87c549
--- /dev/null
+++ b/tests/tests/transition/res/transition/change_transform.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<changeTransform xmlns:android="http://schemas.android.com/apk/res/android"
+ android:reparent="false" android:reparentWithOverlay="false"/>
diff --git a/tests/tests/transition/res/transition/custom_path_motion.xml b/tests/tests/transition/res/transition/custom_path_motion.xml
new file mode 100644
index 0000000..1704419
--- /dev/null
+++ b/tests/tests/transition/res/transition/custom_path_motion.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android">
+ <pathMotion class="android.transition.cts.TransitionInflaterTest$CustomPathMotion"/>
+</changeBounds>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/custom_transition.xml b/tests/tests/transition/res/transition/custom_transition.xml
new file mode 100644
index 0000000..35ee285
--- /dev/null
+++ b/tests/tests/transition/res/transition/custom_transition.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<transition class="android.transition.cts.TransitionInflaterTest$CustomTransition"/>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/explode.xml b/tests/tests/transition/res/transition/explode.xml
new file mode 100644
index 0000000..a038d8b
--- /dev/null
+++ b/tests/tests/transition/res/transition/explode.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<explode xmlns:android="http://schemas.android.com/apk/res/android"
+ android:transitionVisibilityMode="mode_in"/>
diff --git a/tests/tests/transition/res/transition/fade.xml b/tests/tests/transition/res/transition/fade.xml
new file mode 100644
index 0000000..2057014
--- /dev/null
+++ b/tests/tests/transition/res/transition/fade.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<fade xmlns:android="http://schemas.android.com/apk/res/android"
+ android:fadingMode="fade_out"/>
diff --git a/tests/tests/transition/res/transition/pattern_path_motion.xml b/tests/tests/transition/res/transition/pattern_path_motion.xml
new file mode 100644
index 0000000..f794447
--- /dev/null
+++ b/tests/tests/transition/res/transition/pattern_path_motion.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android">
+ <patternPathMotion android:patternPathData="M0 0 L0 100 L100 100"/>
+</changeBounds>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/slide.xml b/tests/tests/transition/res/transition/slide.xml
new file mode 100644
index 0000000..9fde010
--- /dev/null
+++ b/tests/tests/transition/res/transition/slide.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<slide xmlns:android="http://schemas.android.com/apk/res/android"
+ android:slideEdge="top"/>
diff --git a/tests/tests/transition/res/transition/target_classes.xml b/tests/tests/transition/res/transition/target_classes.xml
new file mode 100644
index 0000000..01d1e2d
--- /dev/null
+++ b/tests/tests/transition/res/transition/target_classes.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android">
+ <targets>
+ <target android:targetClass="android.widget.TextView"/>
+ <target android:targetClass="android.widget.ImageView"/>
+ </targets>
+</changeBounds>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/target_ids.xml b/tests/tests/transition/res/transition/target_ids.xml
new file mode 100644
index 0000000..2340e46
--- /dev/null
+++ b/tests/tests/transition/res/transition/target_ids.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android">
+ <targets>
+ <target android:targetId="@+id/hello"/>
+ <target android:targetId="@+id/world"/>
+ </targets>
+</changeBounds>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/target_names.xml b/tests/tests/transition/res/transition/target_names.xml
new file mode 100644
index 0000000..b90cf19
--- /dev/null
+++ b/tests/tests/transition/res/transition/target_names.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<changeBounds xmlns:android="http://schemas.android.com/apk/res/android">
+ <targets>
+ <target android:targetName="hello"/>
+ <target android:targetName="world"/>
+ </targets>
+</changeBounds>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/transition_constructors.xml b/tests/tests/transition/res/transition/transition_constructors.xml
new file mode 100644
index 0000000..e442187
--- /dev/null
+++ b/tests/tests/transition/res/transition/transition_constructors.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
+ <transition class="android.transition.cts.TransitionInflaterTest$InflationFade"/>
+ <transition class="android.transition.cts.TransitionInflaterTest$InflationChangeBounds"/>
+ <transition class="android.transition.cts.TransitionInflaterTest$InflationChangeImageTransform"/>
+ <transition class="android.transition.cts.TransitionInflaterTest$InflationChangeTransform"/>
+ <transition class="android.transition.cts.TransitionInflaterTest$InflationAutoTransition"/>
+ <transition class="android.transition.cts.TransitionInflaterTest$InflationChangeClipBounds"/>
+ <transition class="android.transition.cts.TransitionInflaterTest$InflationChangeScroll"/>
+ <transition class="android.transition.cts.TransitionInflaterTest$InflationExplode"/>
+ <transition class="android.transition.cts.TransitionInflaterTest$InflationSlide"/>
+ <transition class="android.transition.cts.TransitionInflaterTest$InflationTransitionSet"/>
+</transitionSet>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/transition_manager.xml b/tests/tests/transition/res/transition/transition_manager.xml
new file mode 100644
index 0000000..8d3186c
--- /dev/null
+++ b/tests/tests/transition/res/transition/transition_manager.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<transitionManager xmlns:android="http://schemas.android.com/apk/res/android">
+ <transition android:toScene="@layout/scene1"
+ android:transition="@transition/fade"/>
+ <transition android:fromScene="@layout/scene1" android:toScene="@layout/scene2"
+ android:transition="@transition/change_bounds"/>
+</transitionManager>
\ No newline at end of file
diff --git a/tests/tests/transition/res/transition/transition_set.xml b/tests/tests/transition/res/transition/transition_set.xml
new file mode 100644
index 0000000..3b1ff3c
--- /dev/null
+++ b/tests/tests/transition/res/transition/transition_set.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
+ android:transitionOrdering="sequential">
+ <changeBounds/>
+ <fade/>
+</transitionSet>
diff --git a/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java b/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java
index 944ff91..a5da03e 100644
--- a/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java
+++ b/tests/tests/transition/src/android/transition/cts/BaseTransitionTest.java
@@ -89,7 +89,7 @@
}
protected Scene loadScene(final View layout) throws Throwable {
- Scene[] scene = new Scene[1];
+ final Scene[] scene = new Scene[1];
runTestOnUiThread(new Runnable() {
@Override
public void run() {
@@ -101,7 +101,7 @@
}
protected Scene loadScene(final int layoutId) throws Throwable {
- Scene scene[] = new Scene[1];
+ final Scene scene[] = new Scene[1];
runTestOnUiThread(new Runnable() {
@Override
public void run() {
diff --git a/tests/tests/transition/src/android/transition/cts/CaptureValuesTest.java b/tests/tests/transition/src/android/transition/cts/CaptureValuesTest.java
new file mode 100644
index 0000000..84b154a
--- /dev/null
+++ b/tests/tests/transition/src/android/transition/cts/CaptureValuesTest.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+package android.transition.cts;
+
+import android.support.test.filters.MediumTest;
+import android.support.test.filters.SmallTest;
+import android.transition.AutoTransition;
+import android.transition.ChangeBounds;
+import android.transition.ChangeClipBounds;
+import android.transition.ChangeImageTransform;
+import android.transition.ChangeScroll;
+import android.transition.ChangeTransform;
+import android.transition.Explode;
+import android.transition.Fade;
+import android.transition.Slide;
+import android.transition.Transition;
+import android.transition.TransitionManager;
+import android.transition.TransitionSet;
+import android.transition.TransitionValues;
+import android.util.ArrayMap;
+
+@MediumTest
+public class CaptureValuesTest extends BaseTransitionTest {
+ private ArrayMap<Class<?>, Boolean> mStartCaptured = new ArrayMap<>();
+ private ArrayMap<Class<?>, Boolean> mEndCaptured = new ArrayMap<>();
+
+ /**
+ * Ensures captureValues is called on all Transitions and the proper values are captured.
+ */
+ public void testCaptureValues() throws Throwable {
+ final TransitionSetCaptureValues set = new TransitionSetCaptureValues();
+ set.addTransition(new FadeCaptureValues());
+ set.addTransition(new ChangeBoundsCaptureValues());
+ set.addTransition(new ChangeImageTransformCaptureValues());
+ set.addTransition(new ChangeTransformCaptureValues());
+ set.addTransition(new AutoTransitionCaptureValues());
+ set.addTransition(new ChangeClipBoundsCaptureValues());
+ set.addTransition(new ChangeScrollCaptureValues());
+ set.addTransition(new ExplodeCaptureValues());
+ set.addTransition(new SlideCaptureValues());
+
+ enterScene(R.layout.scene11);
+ set.addTarget(getActivity().findViewById(R.id.redSquare));
+ mTransition = set;
+ resetListener();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ TransitionManager.beginDelayedTransition(mSceneRoot, set);
+ mSceneRoot.invalidate();
+ }
+ });
+ waitForStart();
+ // no transition needs to run, but they should have all captured values.
+
+ for (int i = 0; i < set.getTransitionCount(); i++) {
+ Transition transition = set.getTransitionAt(i);
+ String className = transition.getClass().getSuperclass().getSimpleName().toString();
+ assertNotNull("captureStartValues not called for " + className,
+ mStartCaptured.get(transition.getClass()));
+ assertNotNull("captureEndValues not called for " + className,
+ mEndCaptured.get(transition.getClass()));
+ }
+ assertNotNull(mStartCaptured.get(set.getClass()));
+ assertNotNull(mEndCaptured.get(set.getClass()));
+ }
+
+ private void testCapturedValues(Transition transition, TransitionValues values,
+ boolean isStart) {
+ String[] properties = transition.getTransitionProperties();
+ if (transition instanceof TransitionSet) {
+ assertNull(properties);
+ } else {
+ String className = transition.getClass().getSuperclass().getSimpleName().toString();
+ assertNotNull(className + " should have non-null transition properties", properties);
+ assertTrue(properties.length > 0);
+
+ for (String property : properties) {
+ assertTrue(className + " should have written to property " + property,
+ values.values.keySet().contains(property));
+ }
+ }
+ if (isStart) {
+ mStartCaptured.put(transition.getClass(), true);
+ } else {
+ mEndCaptured.put(transition.getClass(), true);
+ }
+ }
+
+ public class FadeCaptureValues extends Fade {
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ super.captureStartValues(transitionValues);
+ testCapturedValues(this, transitionValues, true);
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ super.captureEndValues(transitionValues);
+ testCapturedValues(this, transitionValues, false);
+ }
+ }
+
+ public class ChangeBoundsCaptureValues extends ChangeBounds {
+ public ChangeBoundsCaptureValues() {
+ super();
+ setResizeClip(true);
+ setReparent(true);
+ }
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ super.captureStartValues(transitionValues);
+ testCapturedValues(this, transitionValues, true);
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ super.captureEndValues(transitionValues);
+ testCapturedValues(this, transitionValues, false);
+ }
+ }
+
+ public class ChangeImageTransformCaptureValues extends ChangeImageTransform {
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ super.captureStartValues(transitionValues);
+ testCapturedValues(this, transitionValues, true);
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ super.captureEndValues(transitionValues);
+ testCapturedValues(this, transitionValues, false);
+ }
+ }
+
+ public class ChangeTransformCaptureValues extends ChangeTransform {
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ super.captureStartValues(transitionValues);
+ testCapturedValues(this, transitionValues, true);
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ super.captureEndValues(transitionValues);
+ testCapturedValues(this, transitionValues, false);
+ }
+ }
+
+ public class AutoTransitionCaptureValues extends AutoTransition {
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ super.captureStartValues(transitionValues);
+ testCapturedValues(this, transitionValues, true);
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ super.captureEndValues(transitionValues);
+ testCapturedValues(this, transitionValues, false);
+ }
+ }
+
+ public class ChangeClipBoundsCaptureValues extends ChangeClipBounds {
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ super.captureStartValues(transitionValues);
+ testCapturedValues(this, transitionValues, true);
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ super.captureEndValues(transitionValues);
+ testCapturedValues(this, transitionValues, false);
+ }
+ }
+
+ public class ChangeScrollCaptureValues extends ChangeScroll {
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ super.captureStartValues(transitionValues);
+ testCapturedValues(this, transitionValues, true);
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ super.captureEndValues(transitionValues);
+ testCapturedValues(this, transitionValues, false);
+ }
+ }
+
+ public class ExplodeCaptureValues extends Explode {
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ super.captureStartValues(transitionValues);
+ testCapturedValues(this, transitionValues, true);
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ super.captureEndValues(transitionValues);
+ testCapturedValues(this, transitionValues, false);
+ }
+ }
+
+ public class SlideCaptureValues extends Slide {
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ super.captureStartValues(transitionValues);
+ testCapturedValues(this, transitionValues, true);
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ super.captureEndValues(transitionValues);
+ testCapturedValues(this, transitionValues, false);
+ }
+ }
+ public class TransitionSetCaptureValues extends TransitionSet {
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ super.captureStartValues(transitionValues);
+ testCapturedValues(this, transitionValues, true);
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ super.captureEndValues(transitionValues);
+ testCapturedValues(this, transitionValues, false);
+ }
+ }
+}
diff --git a/tests/tests/transition/src/android/transition/cts/PatternPathMotionTest.java b/tests/tests/transition/src/android/transition/cts/PatternPathMotionTest.java
index 5485b4a..6655213 100644
--- a/tests/tests/transition/src/android/transition/cts/PatternPathMotionTest.java
+++ b/tests/tests/transition/src/android/transition/cts/PatternPathMotionTest.java
@@ -47,5 +47,14 @@
assertPathMatches(expected, pathMotion.getPath(0, 0, 0, 100));
}
+
+ public void testSetPatternPath() throws Throwable {
+ Path pattern = new Path();
+ pattern.addArc(0, 0, 100, 100, 0, 180);
+
+ PatternPathMotion patternPathMotion = new PatternPathMotion();
+ patternPathMotion.setPatternPath(pattern);
+ assertSame(pattern, patternPathMotion.getPatternPath());
+ }
}
diff --git a/tests/tests/transition/src/android/transition/cts/PropagationTest.java b/tests/tests/transition/src/android/transition/cts/PropagationTest.java
new file mode 100644
index 0000000..7b49c15
--- /dev/null
+++ b/tests/tests/transition/src/android/transition/cts/PropagationTest.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+package android.transition.cts;
+
+import android.graphics.Rect;
+import android.transition.CircularPropagation;
+import android.transition.SidePropagation;
+import android.transition.Transition;
+import android.transition.TransitionValues;
+import android.view.Gravity;
+import android.view.View;
+
+public class PropagationTest extends BaseTransitionTest {
+ public void testCircularPropagation() throws Throwable {
+ enterScene(R.layout.scene10);
+ CircularPropagation propagation = new CircularPropagation();
+ mTransition.setPropagation(propagation);
+ final TransitionValues redValues = new TransitionValues();
+ redValues.view = getActivity().findViewById(R.id.redSquare);
+ propagation.captureValues(redValues);
+
+ // Only the reported propagation properties are set
+ for (String prop : propagation.getPropagationProperties()) {
+ assertTrue(redValues.values.keySet().contains(prop));
+ }
+ assertEquals(propagation.getPropagationProperties().length, redValues.values.size());
+
+ // check the visibility
+ assertEquals(View.VISIBLE, propagation.getViewVisibility(redValues));
+ assertEquals(View.GONE, propagation.getViewVisibility(null));
+
+ // Check the positions
+ int[] pos = new int[2];
+ redValues.view.getLocationOnScreen(pos);
+ pos[0] += redValues.view.getWidth() / 2;
+ pos[1] += redValues.view.getHeight() / 2;
+ assertEquals(pos[0], propagation.getViewX(redValues));
+ assertEquals(pos[1], propagation.getViewY(redValues));
+
+ mTransition.setEpicenterCallback(new Transition.EpicenterCallback() {
+ @Override
+ public Rect onGetEpicenter(Transition transition) {
+ return new Rect(0, 0, redValues.view.getWidth(), redValues.view.getHeight());
+ }
+ });
+
+ long redDelay = getDelay(R.id.redSquare);
+ // red square's delay should be roughly 0 since it is at the epicenter
+ assertEquals(0f, redDelay, 30f);
+
+ // The green square is on the upper-right
+ long greenDelay = getDelay(R.id.greenSquare);
+ assertTrue(greenDelay < redDelay);
+
+ // The blue square is on the lower-right
+ long blueDelay = getDelay(R.id.blueSquare);
+ assertTrue(blueDelay < greenDelay);
+
+ // Test propagation speed
+ propagation.setPropagationSpeed(1000000000f);
+ assertEquals(0, getDelay(R.id.blueSquare));
+ }
+
+ public void testSidePropagationBottom() throws Throwable {
+ SidePropagation propagation = new SidePropagation();
+ propagation.setSide(Gravity.BOTTOM);
+ mTransition.setEpicenterCallback(new Transition.EpicenterCallback() {
+ @Override
+ public Rect onGetEpicenter(Transition transition) {
+ return new Rect(0, 0, 1, 1);
+ }
+ });
+ mTransition.setPropagation(propagation);
+
+ enterScene(R.layout.scene10);
+
+ // The red square is on the upper-left
+ long redDelay = getDelay(R.id.redSquare);
+
+ // The green square is on the upper-right
+ long greenDelay = getDelay(R.id.greenSquare);
+
+ // The blue square is on the lower-right
+ long blueDelay = getDelay(R.id.blueSquare);
+
+ // The yellow square is on the lower-left
+ long yellowDelay = getDelay(R.id.yellowSquare);
+
+ assertTrue(redDelay > greenDelay);
+ assertTrue(redDelay > yellowDelay);
+ assertTrue(greenDelay > blueDelay);
+ assertTrue(yellowDelay > blueDelay);
+
+ // Test propagation speed
+ propagation.setPropagationSpeed(1000000000f);
+ assertEquals(0, getDelay(R.id.blueSquare));
+ }
+
+ public void testSidePropagationTop() throws Throwable {
+ SidePropagation propagation = new SidePropagation();
+ propagation.setSide(Gravity.TOP);
+ mTransition.setEpicenterCallback(new Transition.EpicenterCallback() {
+ @Override
+ public Rect onGetEpicenter(Transition transition) {
+ return new Rect(0, 0, 1, 1);
+ }
+ });
+ mTransition.setPropagation(propagation);
+
+ enterScene(R.layout.scene10);
+
+ // The red square is on the upper-left
+ long redDelay = getDelay(R.id.redSquare);
+
+ // The green square is on the upper-right
+ long greenDelay = getDelay(R.id.greenSquare);
+
+ // The blue square is on the lower-right
+ long blueDelay = getDelay(R.id.blueSquare);
+
+ // The yellow square is on the lower-left
+ long yellowDelay = getDelay(R.id.yellowSquare);
+
+ assertTrue(yellowDelay > redDelay);
+ assertTrue(yellowDelay > blueDelay);
+ assertTrue(redDelay > greenDelay);
+ assertTrue(blueDelay > greenDelay);
+ }
+
+ public void testSidePropagationRight() throws Throwable {
+ SidePropagation propagation = new SidePropagation();
+ propagation.setSide(Gravity.RIGHT);
+ mTransition.setEpicenterCallback(new Transition.EpicenterCallback() {
+ @Override
+ public Rect onGetEpicenter(Transition transition) {
+ return new Rect(0, 0, 1, 1);
+ }
+ });
+ mTransition.setPropagation(propagation);
+
+ enterScene(R.layout.scene10);
+
+ // The red square is on the upper-left
+ long redDelay = getDelay(R.id.redSquare);
+
+ // The green square is on the upper-right
+ long greenDelay = getDelay(R.id.greenSquare);
+
+ // The blue square is on the lower-right
+ long blueDelay = getDelay(R.id.blueSquare);
+
+ // The yellow square is on the lower-left
+ long yellowDelay = getDelay(R.id.yellowSquare);
+
+ assertTrue(redDelay > greenDelay);
+ assertTrue(redDelay > yellowDelay);
+ assertTrue(yellowDelay > blueDelay);
+ assertTrue(greenDelay > blueDelay);
+ }
+
+ public void testSidePropagationLeft() throws Throwable {
+ SidePropagation propagation = new SidePropagation();
+ propagation.setSide(Gravity.LEFT);
+ mTransition.setEpicenterCallback(new Transition.EpicenterCallback() {
+ @Override
+ public Rect onGetEpicenter(Transition transition) {
+ return new Rect(0, 0, 1, 1);
+ }
+ });
+ mTransition.setPropagation(propagation);
+
+ enterScene(R.layout.scene10);
+
+ // The red square is on the upper-left
+ long redDelay = getDelay(R.id.redSquare);
+
+ // The green square is on the upper-right
+ long greenDelay = getDelay(R.id.greenSquare);
+
+ // The blue square is on the lower-right
+ long blueDelay = getDelay(R.id.blueSquare);
+
+ // The yellow square is on the lower-left
+ long yellowDelay = getDelay(R.id.yellowSquare);
+
+ assertTrue(greenDelay > redDelay);
+ assertTrue(greenDelay > blueDelay);
+ assertTrue(redDelay > yellowDelay);
+ assertTrue(blueDelay > yellowDelay);
+ }
+
+ private TransitionValues capturePropagationValues(int viewId) {
+ TransitionValues transitionValues = new TransitionValues();
+ transitionValues.view = mSceneRoot.findViewById(viewId);
+ mTransition.getPropagation().captureValues(transitionValues);
+ return transitionValues;
+ }
+
+ private long getDelay(int viewId) {
+ TransitionValues transitionValues = capturePropagationValues(viewId);
+ return mTransition.getPropagation().
+ getStartDelay(mSceneRoot, mTransition, transitionValues, null);
+ }
+}
diff --git a/tests/tests/transition/src/android/transition/cts/SceneTest.java b/tests/tests/transition/src/android/transition/cts/SceneTest.java
index 2785714..48fb6c1 100644
--- a/tests/tests/transition/src/android/transition/cts/SceneTest.java
+++ b/tests/tests/transition/src/android/transition/cts/SceneTest.java
@@ -17,12 +17,12 @@
import android.transition.Scene;
import android.view.View;
+import android.view.ViewGroup;
public class SceneTest extends BaseTransitionTest {
-
- public SceneTest() {
- }
-
+ /**
+ * Test Scene(ViewGroup) with enterAction and exitAction
+ */
public void testDynamicConstructor() throws Throwable {
Scene scene = new Scene(mSceneRoot);
assertEquals(mSceneRoot, scene.getSceneRoot());
@@ -52,32 +52,34 @@
assertNull(mSceneRoot.findViewById(R.id.redSquare));
}
+ /**
+ * Test Scene(ViewGroup, View)
+ */
public void testViewConstructor() throws Throwable {
View view = loadLayout(R.layout.scene1);
- Scene scene = new Scene(mSceneRoot, view);
- assertEquals(mSceneRoot, scene.getSceneRoot());
- CallCheck enterCheck = new CallCheck();
- scene.setEnterAction(enterCheck);
- CallCheck exitCheck = new CallCheck();
- scene.setExitAction(exitCheck);
- enterScene(scene);
-
- assertTrue(enterCheck.wasRun);
- assertFalse(exitCheck.wasRun);
-
- View redSquare = mActivity.findViewById(R.id.redSquare);
- assertNotNull(redSquare);
-
- exitScene(scene);
- assertNotNull(mSceneRoot.findViewById(R.id.redSquare));
- assertTrue(exitCheck.wasRun);
-
- enterScene(R.layout.scene4);
- assertNull(mSceneRoot.findViewById(R.id.redSquare));
+ constructorTest(new Scene(mSceneRoot, view));
}
+ /**
+ * Test Scene(ViewGroup, ViewGroup)
+ */
+ public void testDeprecatedConstructor() throws Throwable {
+ View view = loadLayout(R.layout.scene1);
+ constructorTest(new Scene(mSceneRoot, (ViewGroup) view));
+ }
+
+ /**
+ * Test Scene.getSceneForLayout
+ */
public void testFactory() throws Throwable {
Scene scene = loadScene(R.layout.scene1);
+ constructorTest(scene);
+ }
+
+ /**
+ * Tests that the Scene was constructed properly from a scene1
+ */
+ private void constructorTest(Scene scene) throws Throwable {
assertEquals(mSceneRoot, scene.getSceneRoot());
CallCheck enterCheck = new CallCheck();
scene.setEnterAction(enterCheck);
@@ -94,8 +96,6 @@
exitScene(scene);
assertNotNull(mSceneRoot.findViewById(R.id.redSquare));
assertTrue(exitCheck.wasRun);
- enterScene(R.layout.scene4);
- assertNull(mSceneRoot.findViewById(R.id.redSquare));
}
private static class CallCheck implements Runnable {
diff --git a/tests/tests/transition/src/android/transition/cts/TransitionInflaterTest.java b/tests/tests/transition/src/android/transition/cts/TransitionInflaterTest.java
new file mode 100644
index 0000000..22c0616
--- /dev/null
+++ b/tests/tests/transition/src/android/transition/cts/TransitionInflaterTest.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+package android.transition.cts;
+
+import android.content.Context;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.support.test.filters.MediumTest;
+import android.transition.ArcMotion;
+import android.transition.AutoTransition;
+import android.transition.ChangeBounds;
+import android.transition.ChangeClipBounds;
+import android.transition.ChangeImageTransform;
+import android.transition.ChangeScroll;
+import android.transition.ChangeTransform;
+import android.transition.Explode;
+import android.transition.Fade;
+import android.transition.PathMotion;
+import android.transition.PatternPathMotion;
+import android.transition.Scene;
+import android.transition.Slide;
+import android.transition.Transition;
+import android.transition.TransitionInflater;
+import android.transition.TransitionManager;
+import android.transition.TransitionSet;
+import android.transition.TransitionValues;
+import android.transition.Visibility;
+import android.transition.cts.R;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.List;
+
+@MediumTest
+public class TransitionInflaterTest extends BaseTransitionTest {
+ public void testInflationConstructors() throws Throwable {
+ TransitionInflater inflater = TransitionInflater.from(mActivity);
+ Transition transition = inflater.inflateTransition(R.transition.transition_constructors);
+ assertTrue(transition instanceof TransitionSet);
+ TransitionSet set = (TransitionSet) transition;
+ assertEquals(10, set.getTransitionCount());
+ }
+
+ public void testInflation() {
+ TransitionInflater inflater = TransitionInflater.from(mActivity);
+ assureFadeProperties(inflater.inflateTransition(R.transition.fade));
+ assureChangeBoundsProperties(inflater.inflateTransition(R.transition.change_bounds));
+ assureSlideProperties(inflater.inflateTransition(R.transition.slide));
+ assureExplodeProperties(inflater.inflateTransition(R.transition.explode));
+ assureChangeImageTransformProperties(
+ inflater.inflateTransition(R.transition.change_image_transform));
+ assureChangeTransformProperties(inflater.inflateTransition(R.transition.change_transform));
+ assureChangeClipBoundsProperties(
+ inflater.inflateTransition(R.transition.change_clip_bounds));
+ assureAutoTransitionProperties(inflater.inflateTransition(R.transition.auto_transition));
+ assureChangeScrollProperties(inflater.inflateTransition(R.transition.change_scroll));
+ assureTransitionSetProperties(inflater.inflateTransition(R.transition.transition_set));
+ assureCustomTransitionProperties(
+ inflater.inflateTransition(R.transition.custom_transition));
+ testTargetIds(inflater.inflateTransition(R.transition.target_ids));
+ testTargetNames(inflater.inflateTransition(R.transition.target_names));
+ testTargetClass(inflater.inflateTransition(R.transition.target_classes));
+ testArcMotion(inflater.inflateTransition(R.transition.arc_motion));
+ testCustomPathMotion(inflater.inflateTransition(R.transition.custom_path_motion));
+ testPatternPathMotion(inflater.inflateTransition(R.transition.pattern_path_motion));
+ }
+
+ public void testInflateTransitionManager() throws Throwable {
+ TransitionInflater inflater = TransitionInflater.from(mActivity);
+ TransitionManager transitionManager =
+ inflater.inflateTransitionManager(R.transition.transition_manager, mSceneRoot);
+ assertNotNull(transitionManager);
+
+ Scene scene1 = Scene.getSceneForLayout(mSceneRoot, R.layout.scene1, mActivity);
+ Transition transition = transitionManager.getTransition(scene1);
+ assertNotNull(transition);
+ assertTrue(transition instanceof Fade);
+ enterScene(scene1);
+
+ Scene scene2 = Scene.getSceneForLayout(mSceneRoot, R.layout.scene2, mActivity);
+ transition = transitionManager.getTransition(scene2);
+ assertNotNull(transition);
+ assertTrue(transition instanceof ChangeBounds);
+ }
+
+ private void assureFadeProperties(Transition transition) {
+ assertTrue(transition instanceof Fade);
+ Fade fade = (Fade) transition;
+ assertEquals(Fade.OUT, fade.getMode());
+ }
+
+ private void assureChangeBoundsProperties(Transition transition) {
+ assertTrue(transition instanceof ChangeBounds);
+ ChangeBounds changeBounds = (ChangeBounds) transition;
+ assertTrue(changeBounds.getResizeClip());
+ }
+
+ private void assureSlideProperties(Transition transition) {
+ assertTrue(transition instanceof Slide);
+ Slide slide = (Slide) transition;
+ assertEquals(Gravity.TOP, slide.getSlideEdge());
+ }
+
+ private void assureExplodeProperties(Transition transition) {
+ assertTrue(transition instanceof Explode);
+ Visibility visibility = (Visibility) transition;
+ assertEquals(Visibility.MODE_IN, visibility.getMode());
+ }
+
+ private void assureChangeImageTransformProperties(Transition transition) {
+ assertTrue(transition instanceof ChangeImageTransform);
+ }
+
+ private void assureChangeTransformProperties(Transition transition) {
+ assertTrue(transition instanceof ChangeTransform);
+ ChangeTransform changeTransform = (ChangeTransform) transition;
+ assertFalse(changeTransform.getReparent());
+ assertFalse(changeTransform.getReparentWithOverlay());
+ }
+
+ private void assureChangeClipBoundsProperties(Transition transition) {
+ assertTrue(transition instanceof ChangeClipBounds);
+ }
+
+ private void assureAutoTransitionProperties(Transition transition) {
+ assertTrue(transition instanceof AutoTransition);
+ }
+
+ private void assureChangeScrollProperties(Transition transition) {
+ assertTrue(transition instanceof ChangeScroll);
+ }
+
+ private void assureTransitionSetProperties(Transition transition) {
+ assertTrue(transition instanceof TransitionSet);
+ TransitionSet set = (TransitionSet) transition;
+ assertEquals(TransitionSet.ORDERING_SEQUENTIAL, set.getOrdering());
+ assertEquals(2, set.getTransitionCount());
+ assertTrue(set.getTransitionAt(0) instanceof ChangeBounds);
+ assertTrue(set.getTransitionAt(1) instanceof Fade);
+ }
+
+ private void assureCustomTransitionProperties(Transition transition) {
+ assertTrue(transition instanceof CustomTransition);
+ }
+
+ private void testTargetIds(Transition transition) {
+ List<Integer> targets = transition.getTargetIds();
+ assertNotNull(targets);
+ assertEquals(2, targets.size());
+ assertEquals(R.id.hello, (int) targets.get(0));
+ assertEquals(R.id.world, (int) targets.get(1));
+ }
+
+ private void testTargetNames(Transition transition) {
+ List<String> targets = transition.getTargetNames();
+ assertNotNull(targets);
+ assertEquals(2, targets.size());
+ assertEquals("hello", targets.get(0));
+ assertEquals("world", targets.get(1));
+ }
+
+ private void testTargetClass(Transition transition) {
+ List<Class> targets = transition.getTargetTypes();
+ assertNotNull(targets);
+ assertEquals(2, targets.size());
+ assertEquals(TextView.class, targets.get(0));
+ assertEquals(ImageView.class, targets.get(1));
+ }
+
+ private void testArcMotion(Transition transition) {
+ assertNotNull(transition);
+ PathMotion motion = transition.getPathMotion();
+ assertNotNull(motion);
+ assertTrue(motion instanceof ArcMotion);
+ ArcMotion arcMotion = (ArcMotion) motion;
+ assertEquals(1f, arcMotion.getMinimumVerticalAngle(), 0.01f);
+ assertEquals(2f, arcMotion.getMinimumHorizontalAngle(), 0.01f);
+ assertEquals(53f, arcMotion.getMaximumAngle(), 0.01f);
+ }
+
+ private void testCustomPathMotion(Transition transition) {
+ assertNotNull(transition);
+ PathMotion motion = transition.getPathMotion();
+ assertNotNull(motion);
+ assertTrue(motion instanceof CustomPathMotion);
+ }
+
+ private void testPatternPathMotion(Transition transition) {
+ assertNotNull(transition);
+ PathMotion motion = transition.getPathMotion();
+ assertNotNull(motion);
+ assertTrue(motion instanceof PatternPathMotion);
+ PatternPathMotion pattern = (PatternPathMotion) motion;
+ Path path = pattern.getPatternPath();
+ PathMeasure measure = new PathMeasure(path, false);
+ assertEquals(200f, measure.getLength(), 0.1f);
+ }
+
+ public static class CustomTransition extends Transition {
+ public CustomTransition() {
+ fail("Default constructor was not expected");
+ }
+
+ public CustomTransition(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+
+ }
+ }
+
+ public static class CustomPathMotion extends PathMotion {
+ public CustomPathMotion() {
+ fail("default constructor shouldn't be called.");
+ }
+
+ public CustomPathMotion(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public Path getPath(float startX, float startY, float endX, float endY) {
+ return null;
+ }
+ }
+
+ public static class InflationFade extends Fade {
+ public InflationFade(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+ }
+
+ public static class InflationChangeBounds extends ChangeBounds {
+ public InflationChangeBounds(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+ }
+
+ public static class InflationSlide extends Slide {
+ public InflationSlide(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+ }
+
+ public static class InflationTransitionSet extends TransitionSet {
+ public InflationTransitionSet(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+ }
+
+ public static class InflationChangeImageTransform extends ChangeImageTransform {
+ public InflationChangeImageTransform(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+ }
+
+ public static class InflationChangeTransform extends ChangeTransform {
+ public InflationChangeTransform(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+ }
+
+ public static class InflationAutoTransition extends AutoTransition {
+ public InflationAutoTransition(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+ }
+
+ public static class InflationChangeClipBounds extends ChangeClipBounds {
+ public InflationChangeClipBounds(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+ }
+
+ public static class InflationChangeScroll extends ChangeScroll {
+ public InflationChangeScroll(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+ }
+
+ public static class InflationExplode extends Explode {
+ public InflationExplode(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+ }
+}
diff --git a/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java b/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java
index 9eacd1b..a8a653d 100644
--- a/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java
+++ b/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java
@@ -15,11 +15,13 @@
*/
package android.transition.cts;
+import android.graphics.Rect;
import android.transition.cts.R;
import android.transition.Scene;
import android.transition.TransitionManager;
import android.view.View;
+import android.view.ViewTreeObserver;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -57,6 +59,49 @@
});
}
+ public void testDefaultBeginDelayedTransition() throws Throwable {
+ enterScene(R.layout.scene1);
+ final CountDownLatch startLatch = new CountDownLatch(1);
+ mSceneRoot.getViewTreeObserver().addOnPreDrawListener(
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ mSceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
+ startLatch.countDown();
+ return true;
+ }
+ });
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ TransitionManager.beginDelayedTransition(mSceneRoot);
+ }
+ });
+ enterScene(R.layout.scene6);
+ assertTrue(startLatch.await(500, TimeUnit.MILLISECONDS));
+ ensureRedSquareIsMoving();
+ endTransition();
+ }
+
+ private void ensureRedSquareIsMoving() throws InterruptedException {
+ final View view = getActivity().findViewById(R.id.redSquare);
+ assertNotNull(view);
+ // We should see a ChangeBounds on redSquare
+ final Rect position = new Rect(view.getLeft(), view.getTop(), view.getRight(),
+ view.getBottom());
+ final CountDownLatch latch = new CountDownLatch(1);
+ view.postOnAnimationDelayed(new Runnable() {
+ @Override
+ public void run() {
+ Rect next = new Rect(view.getLeft(), view.getTop(), view.getRight(),
+ view.getBottom());
+ assertTrue(!next.equals(position));
+ latch.countDown();
+ }
+ }, 20);
+ assertTrue(latch.await(500, TimeUnit.MILLISECONDS));
+ }
+
public void testGo() throws Throwable {
startTransition(R.layout.scene1);
waitForStart();
@@ -77,6 +122,30 @@
});
}
+ public void testDefaultGo() throws Throwable {
+ enterScene(R.layout.scene1);
+ final CountDownLatch startLatch = new CountDownLatch(1);
+ mSceneRoot.getViewTreeObserver().addOnPreDrawListener(
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ mSceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
+ startLatch.countDown();
+ return true;
+ }
+ });
+ final Scene scene6 = loadScene(R.layout.scene6);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ TransitionManager.go(scene6);
+ }
+ });
+ assertTrue(startLatch.await(500, TimeUnit.MILLISECONDS));
+ ensureRedSquareIsMoving();
+ endTransition();
+ }
+
public void testSetTransition1() throws Throwable {
final TransitionManager transitionManager = new TransitionManager();
diff --git a/tests/tests/transition/src/android/transition/cts/TransitionTest.java b/tests/tests/transition/src/android/transition/cts/TransitionTest.java
index 9ae568a..71b22fe 100644
--- a/tests/tests/transition/src/android/transition/cts/TransitionTest.java
+++ b/tests/tests/transition/src/android/transition/cts/TransitionTest.java
@@ -23,6 +23,7 @@
import android.transition.ArcMotion;
import android.transition.AutoTransition;
import android.transition.ChangeBounds;
+import android.transition.CircularPropagation;
import android.transition.PathMotion;
import android.transition.Scene;
import android.transition.Transition;
@@ -240,6 +241,7 @@
public void testIsTransitionRequired() throws Throwable {
enterScene(R.layout.scene1);
mTransition = new NotRequiredTransition();
+ assertFalse(mTransition.isTransitionRequired(null, null));
resetListener();
runTestOnUiThread(new Runnable() {
@Override
@@ -315,6 +317,19 @@
endTransition();
}
+ public void testExcludeChildrenClass() throws Throwable {
+ enterScene(R.layout.scene1);
+ mTransition.excludeChildren(RelativeLayout.class, true);
+ startTransition(R.layout.scene2);
+ waitForEnd(0); // Should already be ended, since no children are transitioning
+
+ resetListener();
+ mTransition.excludeChildren(RelativeLayout.class, false); // remove it
+ startTransition(R.layout.scene1);
+ assertEquals(1, mListener.endLatch.getCount()); // It is running
+ endTransition();
+ }
+
public void testExcludeTargetView() throws Throwable {
View layout1 = loadLayout(R.layout.scene1);
Scene scene1 = loadScene(layout1);
@@ -383,6 +398,7 @@
}
public void testEpicenter() throws Throwable {
+ assertNull(mTransition.getEpicenter());
EpicenterCallback callback = new EpicenterCallback() {
@Override
public Rect onGetEpicenter(Transition transition) {
@@ -390,7 +406,8 @@
}
};
mTransition.setEpicenterCallback(callback);
- assertEquals(callback, mTransition.getEpicenterCallback());
+ assertSame(callback, mTransition.getEpicenterCallback());
+ assertEquals(new Rect(0, 0, 1, 1), mTransition.getEpicenter());
}
public void testInterpolator() throws Throwable {
@@ -467,6 +484,14 @@
endTransition();
}
+ public void testSetPropagation() throws Throwable {
+ Transition transition = new ChangeBounds();
+ assertNull(transition.getPropagation());
+ TransitionPropagation propagation = new CircularPropagation();
+ transition.setPropagation(propagation);
+ assertSame(propagation, transition.getPropagation());
+ }
+
public void testStartDelay() throws Throwable {
CaptureAnimatorTransition transition = new CaptureAnimatorTransition();
mTransition = transition;
@@ -489,10 +514,13 @@
public void testTransitionValues() throws Throwable {
enterScene(R.layout.scene1);
- mTransition = new CheckTransitionValuesTransition();
+ CheckTransitionValuesTransition transition = new CheckTransitionValuesTransition();
+ mTransition = transition;
mTransition.setDuration(10);
resetListener();
- startTransition(R.layout.scene4);
+ startTransition(R.layout.scene2);
+ assertTrue(transition.onDisappearCalled.await(500, TimeUnit.MILLISECONDS));
+ assertTrue(transition.onAppearCalled.await(500, TimeUnit.MILLISECONDS));
// The transition has all the asserts in it, so we can just end it now.
endTransition();
}
@@ -515,6 +543,29 @@
waitForEnd(400);
}
+ public void testGetTransitionProperties() throws Throwable {
+ enterScene(R.layout.scene1);
+ // Make the transition make changes to properties in getTransitionProperties.
+ TransitionPropertiesTransition transition = new TransitionPropertiesTransition(false);
+ mTransition = transition;
+ resetListener();
+ startTransition(R.layout.scene2);
+ assertTrue(transition.latch.await(500, TimeUnit.MILLISECONDS));
+ endTransition();
+
+ // Now make the transition only make changes to unimportant properties.
+ transition = new TransitionPropertiesTransition(true);
+ mTransition = transition;
+ resetListener();
+ startTransition(R.layout.scene1);
+ assertTrue(mListener.endLatch.await(500, TimeUnit.MILLISECONDS));
+ // createAnimator shouldn't have been called.
+ assertEquals(1, transition.latch.getCount());
+
+ assertNotNull(transition.getTransitionProperties());
+ assertEquals(1, transition.getTransitionProperties().length);
+ }
+
private class NotRequiredTransition extends TestTransition {
@Override
public boolean isTransitionRequired(TransitionValues startValues,
@@ -551,9 +602,12 @@
}
private class CheckTransitionValuesTransition extends TestTransition {
+ public CountDownLatch onAppearCalled = new CountDownLatch(1);
+ public CountDownLatch onDisappearCalled = new CountDownLatch(1);
@Override
public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
TransitionValues endValues) {
+ onAppearCalled.countDown();
assertNull(getTransitionValues(endValues.view, true));
assertEquals(endValues, getTransitionValues(endValues.view, false));
return super.onAppear(sceneRoot, view, startValues, endValues);
@@ -562,6 +616,7 @@
@Override
public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
TransitionValues endValues) {
+ onDisappearCalled.countDown();
assertNull(getTransitionValues(startValues.view, false));
assertEquals(startValues, getTransitionValues(startValues.view, true));
return super.onDisappear(sceneRoot, view, startValues, endValues);
@@ -576,5 +631,48 @@
startLatch.countDown();
}
}
+
+ private static class TransitionPropertiesTransition extends Transition {
+ private static final String SIDE_PROP = "prop1";
+ private static final String IMPORTANT_PROP = "prop2";
+ private static final String[] PROPERTIES = {
+ IMPORTANT_PROP
+ };
+
+ private boolean mOnlyUnimportant;
+ public CountDownLatch latch = new CountDownLatch(1);
+
+ public TransitionPropertiesTransition(boolean onlyUnimportant) {
+ mOnlyUnimportant = onlyUnimportant;
+ }
+
+ @Override
+ public String[] getTransitionProperties() {
+ return PROPERTIES;
+ }
+
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ transitionValues.values.put(SIDE_PROP, 1);
+ transitionValues.values.put(IMPORTANT_PROP, 1);
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ transitionValues.values.put(SIDE_PROP, 2);
+ int val = mOnlyUnimportant ? 1 : 2;
+ transitionValues.values.put(IMPORTANT_PROP, val);
+ }
+
+ @Override
+ public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
+ TransitionValues endValues) {
+ if (startValues != null && endValues != null) {
+ latch.countDown();
+ }
+
+ return null;
+ }
+ }
}
diff --git a/tests/tests/transition/src/android/transition/cts/VisibilityTest.java b/tests/tests/transition/src/android/transition/cts/VisibilityTest.java
index 9b91a36..81977a4 100644
--- a/tests/tests/transition/src/android/transition/cts/VisibilityTest.java
+++ b/tests/tests/transition/src/android/transition/cts/VisibilityTest.java
@@ -15,9 +15,15 @@
*/
package android.transition.cts;
+import android.animation.Animator;
+import android.transition.TransitionManager;
import android.transition.TransitionValues;
import android.transition.Visibility;
import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
public class VisibilityTest extends BaseTransitionTest {
Visibility mVisibilityTransition;
@@ -104,5 +110,102 @@
mTransition.captureStartValues(goneValues);
assertFalse(mVisibilityTransition.isVisible(goneValues));
}
+
+ public void testOnAppear() throws Throwable {
+ enterScene(R.layout.scene4);
+ AppearTransition transition = new AppearTransition();
+ mTransition = transition;
+ resetListener();
+ startTransition(R.layout.scene5);
+ assertTrue(transition.onAppearCalled.await(500, TimeUnit.MILLISECONDS));
+ // No need to end the transition since AppearTransition doesn't create
+ // any animators.
+ }
+
+ public void testOnDisppear() throws Throwable {
+ // First, test with overlay
+ enterScene(R.layout.scene5);
+ DisappearTransition transition = new DisappearTransition(true);
+ mTransition = transition;
+ resetListener();
+ startTransition(R.layout.scene4);
+ assertTrue(transition.onDisppearCalled.await(500, TimeUnit.MILLISECONDS));
+ // No need to end the transition since DisappearTransition doesn't create
+ // any animators.
+
+ // Next test without overlay
+ enterScene(R.layout.scene5);
+ transition = new DisappearTransition(false);
+ mTransition = transition;
+ resetListener();
+ final View text = getActivity().findViewById(R.id.text);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ TransitionManager.beginDelayedTransition(mSceneRoot, mTransition);
+ text.setVisibility(View.GONE);
+ }
+ });
+ assertTrue(transition.onDisppearCalled.await(500, TimeUnit.MILLISECONDS));
+ // No need to end the transition since DisappearTransition doesn't create
+ // any animators.
+ }
+
+ static class AppearTransition extends Visibility {
+ private View mExpectedView;
+ public CountDownLatch onAppearCalled = new CountDownLatch(1);
+ @Override
+ public Animator onAppear(ViewGroup sceneRoot, TransitionValues startValues,
+ int startVisibility, TransitionValues endValues, int endVisibility) {
+ assertNotNull(endValues);
+ mExpectedView = endValues.view;
+ return super.onAppear(sceneRoot, startValues, startVisibility, endValues,
+ endVisibility);
+ }
+
+ @Override
+ public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
+ TransitionValues endValues) {
+ assertSame(mExpectedView, view);
+ onAppearCalled.countDown();
+ return null;
+ }
+ }
+
+ static class DisappearTransition extends Visibility {
+ private View mExpectedView;
+ private final boolean mExpectingOverlay;
+ public CountDownLatch onDisppearCalled = new CountDownLatch(1);
+
+ public DisappearTransition(boolean expectingOverlay) {
+ mExpectingOverlay = expectingOverlay;
+ }
+
+ @Override
+ public Animator onDisappear(ViewGroup sceneRoot, TransitionValues startValues,
+ int startVisibility, TransitionValues endValues, int endVisibility) {
+ assertNotNull(startValues);
+ if (mExpectingOverlay) {
+ assertNull(endValues);
+ mExpectedView = null;
+ } else {
+ assertNotNull(endValues);
+ mExpectedView = endValues.view;
+ }
+ return super.onDisappear(sceneRoot, startValues, startVisibility, endValues,
+ endVisibility);
+ }
+
+ @Override
+ public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
+ TransitionValues endValues) {
+ assertNotNull(view);
+ if (mExpectedView != null) {
+ assertSame(mExpectedView, view);
+ }
+ onDisppearCalled.countDown();
+ return null;
+ }
+ }
}
diff --git a/tests/tests/uirendering/Android.mk b/tests/tests/uirendering/Android.mk
index fd01e10..a2e54d0 100644
--- a/tests/tests/uirendering/Android.mk
+++ b/tests/tests/uirendering/Android.mk
@@ -26,7 +26,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
diff --git a/tests/tests/uirendering/res/drawable-nodpi/golden_blue_circle.png b/tests/tests/uirendering/res/drawable-nodpi/golden_blue_circle.png
new file mode 100644
index 0000000..f587fb7
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/golden_blue_circle.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/golden_dashed_oval.png b/tests/tests/uirendering/res/drawable-nodpi/golden_dashed_oval.png
new file mode 100644
index 0000000..c95568a
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/golden_dashed_oval.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable/dashed_oval.xml b/tests/tests/uirendering/res/drawable/dashed_oval.xml
new file mode 100644
index 0000000..904b016
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable/dashed_oval.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+ -->
+<shape
+ android:shape="oval"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <stroke
+ android:width="2px"
+ android:dashGap="6px"
+ android:dashWidth="2px"
+ android:color="@android:color/black"
+ />
+</shape>
diff --git a/tests/tests/uirendering/res/layout/frame_layout.xml b/tests/tests/uirendering/res/layout/frame_layout.xml
index 0eb1f9b..4ceac5d 100644
--- a/tests/tests/uirendering/res/layout/frame_layout.xml
+++ b/tests/tests/uirendering/res/layout/frame_layout.xml
@@ -17,4 +17,3 @@
android:id="@+id/frame_layout"
android:layout_width="@dimen/test_width"
android:layout_height="@dimen/test_height"/>
-
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/GoldenImageVerifier.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/GoldenImageVerifier.java
index 42e8960..b9816db 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/GoldenImageVerifier.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/GoldenImageVerifier.java
@@ -15,7 +15,9 @@
*/
package android.uirendering.cts.bitmapverifiers;
+import android.content.Context;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.uirendering.cts.bitmapcomparers.BitmapComparer;
import android.uirendering.cts.differencevisualizers.PassFailVisualizer;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
@@ -31,6 +33,10 @@
mBitmapComparer = bitmapComparer;
}
+ public GoldenImageVerifier(Context context, int goldenResId, BitmapComparer bitmapComparer) {
+ this(BitmapFactory.decodeResource(context.getResources(), goldenResId), bitmapComparer);
+ }
+
@Override
public boolean verify(int[] bitmap, int offset, int stride, int width, int height) {
boolean success = mBitmapComparer.verifySame(mGoldenBitmapArray, bitmap, offset, stride,
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
index 1e7a832..8360948 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
@@ -16,12 +16,18 @@
package android.uirendering.cts.testclasses;
+import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Region;
import android.test.suitebuilder.annotation.MediumTest;
+import android.uirendering.cts.bitmapverifiers.ColorVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.util.DisplayMetrics;
+
import org.junit.Test;
import static org.junit.Assert.assertFalse;
@@ -114,4 +120,68 @@
})
.runWithoutVerification();
}
+
+ private void testFailureOnBitmapDraw(Bitmap bitmap) {
+ createTest()
+ .addCanvasClient((canvas, width, height) -> {
+ boolean sawException = false;
+ try {
+ canvas.drawBitmap(bitmap, 0, 0, null);
+ } catch (RuntimeException e) {
+ sawException = true;
+ }
+ assertTrue(sawException);
+ })
+ .runWithoutVerification();
+ }
+
+ @Test
+ public void testFailureOnDrawRecycledBitmap() {
+ Bitmap recycledBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
+ recycledBitmap.recycle();
+ testFailureOnBitmapDraw(recycledBitmap);
+ }
+
+ @Test
+ public void testFailureOnNonPremultipliedBitmap() {
+ Bitmap nonPremultipliedBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
+ nonPremultipliedBitmap.setPremultiplied(false);
+ nonPremultipliedBitmap.setHasAlpha(true);
+ testFailureOnBitmapDraw(nonPremultipliedBitmap);
+ }
+
+ @Test
+ public void testDrawScreenWideBitmap() {
+ createTest()
+ .addCanvasClient((canvas, width, height) -> {
+ DisplayMetrics displayMetrics =
+ getActivity().getResources().getDisplayMetrics();
+ assertTrue(displayMetrics.widthPixels <= canvas.getMaximumBitmapWidth());
+ assertTrue(displayMetrics.heightPixels <= canvas.getMaximumBitmapHeight());
+ Bitmap bitmap = Bitmap.createBitmap(displayMetrics.widthPixels,
+ displayMetrics.heightPixels, Bitmap.Config.ARGB_8888);
+ bitmap.eraseColor(Color.RED);
+ canvas.drawBitmap(bitmap, 0, 0, null);
+ })
+ .runWithVerifier(new ColorVerifier(Color.RED, 0));
+ }
+
+ @Test
+ public void testDrawLargeBitmap() {
+ // verify that HW and SW pipelines can both draw screen-and-a-half sized bitmap
+ createTest()
+ .addCanvasClient((canvas, width, height) -> {
+ DisplayMetrics displayMetrics =
+ getActivity().getResources().getDisplayMetrics();
+
+ int bWidth = displayMetrics.widthPixels * 3 / 2;
+ int bHeight = displayMetrics.heightPixels * 3 / 2;
+ bWidth = Math.min(bWidth, canvas.getMaximumBitmapWidth());
+ bHeight = Math.min(bHeight, canvas.getMaximumBitmapHeight());
+ Bitmap bitmap = Bitmap.createBitmap(bWidth, bHeight, Bitmap.Config.ARGB_8888);
+ bitmap.eraseColor(Color.RED);
+ canvas.drawBitmap(bitmap, 0, 0, null);
+ })
+ .runWithVerifier(new ColorVerifier(Color.RED, 0));
+ }
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java
new file mode 100644
index 0000000..18fd2bc
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.uirendering.cts.testclasses;
+
+import android.graphics.*;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.uirendering.cts.R;
+import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
+import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import org.junit.Test;
+
+@MediumTest
+public class ShapeTests extends ActivityTestBase {
+ @Test
+ public void testDashedOval() {
+ createTest()
+ .addLayout(R.layout.frame_layout,
+ view -> view.setBackgroundResource(R.drawable.dashed_oval))
+ .runWithVerifier(new GoldenImageVerifier(getActivity(),
+ R.drawable.golden_dashed_oval, new MSSIMComparer(0.99)));
+ }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java
new file mode 100644
index 0000000..4a3e7cf
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.uirendering.cts.testclasses;
+
+import android.test.suitebuilder.annotation.MediumTest;
+import android.uirendering.cts.R;
+import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
+import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.uirendering.cts.testinfrastructure.ViewInitializer;
+import android.view.ViewAnimationUtils;
+import org.junit.Test;
+
+@MediumTest
+public class ViewAnimationUtilsTests extends ActivityTestBase {
+ @Test
+ public void testCreateCircularReveal() {
+ createTest()
+ .addLayout(R.layout.blue_padded_layout, (ViewInitializer) view -> {
+ ViewAnimationUtils.createCircularReveal(view, 45, 45, 45, 45)
+ .setDuration(10000) // 10 sec, longer than animation
+ .start();
+ }, true)
+ .runWithVerifier(new GoldenImageVerifier(getActivity(),
+ R.drawable.golden_blue_circle, new MSSIMComparer(0.99)));
+ }
+}
diff --git a/tests/tests/util/Android.mk b/tests/tests/util/Android.mk
index cb1c70a..866e566 100644
--- a/tests/tests/util/Android.mk
+++ b/tests/tests/util/Android.mk
@@ -24,7 +24,7 @@
# Tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-annotations android-support-test ctstestrunner
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/util/src/android/util/cts/MutableTest.java b/tests/tests/util/src/android/util/cts/MutableTest.java
new file mode 100644
index 0000000..e4f6fd9
--- /dev/null
+++ b/tests/tests/util/src/android/util/cts/MutableTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.util.cts;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class MutableTest {
+ @Test
+ public void testMutableBoolean() {
+ MutableBoolean mut = new MutableBoolean(false);
+ assertFalse(mut.value);
+ mut = new MutableBoolean(true);
+ assertTrue(mut.value);
+ }
+
+ @Test
+ public void testMutableByte() {
+ MutableByte mut = new MutableByte((byte) 127);
+ assertEquals(127, mut.value);
+ mut = new MutableByte((byte) -128);
+ assertEquals(-128, mut.value);
+ }
+
+ @Test
+ public void testMutableChar() {
+ MutableChar mut = new MutableChar('a');
+ assertEquals('a', mut.value);
+ mut = new MutableChar('b');
+ assertEquals('b', mut.value);
+ }
+
+ @Test
+ public void testMutableDouble() {
+ MutableDouble mut = new MutableDouble(0);
+ assertEquals(0, mut.value, 0);
+ mut = new MutableDouble(Double.MAX_VALUE);
+ assertEquals(Double.MAX_VALUE, mut.value, 0);
+ }
+
+ @Test
+ public void testMutableFloat() {
+ MutableFloat mut = new MutableFloat(0f);
+ assertEquals(0f, mut.value, 0);
+ mut = new MutableFloat(Float.MAX_VALUE);
+ assertEquals(Float.MAX_VALUE, mut.value, 0);
+ }
+
+ @Test
+ public void testMutableShort() {
+ MutableShort mut = new MutableShort((short) 0);
+ assertEquals(0, mut.value);
+ mut = new MutableShort(Short.MAX_VALUE);
+ assertEquals(Short.MAX_VALUE, mut.value);
+ }
+}
diff --git a/tests/tests/util/src/android/util/cts/PropertyTest.java b/tests/tests/util/src/android/util/cts/PropertyTest.java
index 22ad2c4..3d76e36 100644
--- a/tests/tests/util/src/android/util/cts/PropertyTest.java
+++ b/tests/tests/util/src/android/util/cts/PropertyTest.java
@@ -17,51 +17,62 @@
package android.util.cts;
import android.graphics.Point;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.util.FloatProperty;
import android.util.IntProperty;
import android.util.Property;
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-public class PropertyTest extends TestCase {
+import static org.junit.Assert.*;
- float mFloatValue = -1;
- int mIntValue = -2;
- Point mPointValue = new Point(-3, -4);
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PropertyTest {
+ private float mFloatValue = -1;
+ private int mIntValue = -2;
+ private Point mPointValue = new Point(-3, -4);
+ @Test
public void testProperty() throws Exception {
float testFloatValue = 5;
Point testPointValue = new Point(10, 20);
assertFalse(getFloatProp() == testFloatValue);
assertFalse(getPointProp().equals(testPointValue));
- assertEquals(RAW_FLOAT_PROP.get(this), getFloatProp());
- assertEquals(RAW_POINT_PROP.get(this), getPointProp());
+ assertEquals(getFloatProp(), RAW_FLOAT_PROP.get(this), 0f);
+ assertEquals(getPointProp(), RAW_POINT_PROP.get(this));
RAW_FLOAT_PROP.set(this, testFloatValue);
- assertEquals(RAW_FLOAT_PROP.get(this), mFloatValue);
+ assertEquals(mFloatValue, RAW_FLOAT_PROP.get(this), 0f);
RAW_POINT_PROP.set(this, testPointValue);
- assertEquals(RAW_POINT_PROP.get(this), testPointValue);
+ assertEquals(testPointValue, RAW_POINT_PROP.get(this));
}
+ @Test
public void testFloatProperty() throws Exception {
- float testFloatValue = 5;
+ assertFalse(getFloatProp() == 5);
+ assertEquals(getFloatProp(), FLOAT_PROP.get(this), 0f);
- assertFalse(getFloatProp() == testFloatValue);
- assertEquals(FLOAT_PROP.get(this), getFloatProp());
+ FLOAT_PROP.set(this, 5f);
+ assertEquals(5f, FLOAT_PROP.get(this), 0f);
- FLOAT_PROP.set(this, testFloatValue);
- assertEquals(FLOAT_PROP.get(this), testFloatValue);
+ FLOAT_PROP.setValue(this, 10);
+ assertEquals(10f, FLOAT_PROP.get(this), 0f);
}
+ @Test
public void testIntProperty() throws Exception {
- int testIntValue = 5;
+ assertFalse(getIntProp() == 5);
+ assertEquals(getIntProp(), INT_PROP.get(this).intValue());
- assertFalse(getIntProp() == testIntValue);
- assertEquals(INT_PROP.get(this).intValue(), getIntProp());
+ INT_PROP.set(this, 5);
+ assertEquals(5, INT_PROP.get(this).intValue());
- INT_PROP.set(this, testIntValue);
- assertEquals(INT_PROP.get(this).intValue(), testIntValue);
+ INT_PROP.setValue(this, 10);
+ assertEquals(10, INT_PROP.get(this).intValue());
}
// Utility methods to get/set instance values. Used by Property classes below.
@@ -91,9 +102,9 @@
}
// Properties. RAW subclass from the generic Property class, the others subclass from
- // the primtive-friendly IntProperty and FloatProperty subclasses.
+ // the primitive-friendly IntProperty and FloatProperty subclasses.
- public static final Property<PropertyTest, Point> RAW_POINT_PROP =
+ private static final Property<PropertyTest, Point> RAW_POINT_PROP =
new Property<PropertyTest, Point>(Point.class, "rawPoint") {
@Override
public void set(PropertyTest object, Point value) {
@@ -106,7 +117,7 @@
}
};
- public static final Property<PropertyTest, Float> RAW_FLOAT_PROP =
+ private static final Property<PropertyTest, Float> RAW_FLOAT_PROP =
new Property<PropertyTest, Float>(Float.class, "rawFloat") {
@Override
public void set(PropertyTest object, Float value) {
@@ -119,7 +130,7 @@
}
};
- public static final Property<PropertyTest, Float> FLOAT_PROP =
+ private static final FloatProperty<PropertyTest> FLOAT_PROP =
new FloatProperty<PropertyTest>("float") {
@Override
@@ -133,7 +144,7 @@
}
};
- public static final Property<PropertyTest, Integer> INT_PROP =
+ private static final IntProperty<PropertyTest> INT_PROP =
new IntProperty<PropertyTest>("int") {
@Override
diff --git a/tests/tests/util/src/android/util/cts/RationalTest.java b/tests/tests/util/src/android/util/cts/RationalTest.java
index ab5c063..dabb29d 100644
--- a/tests/tests/util/src/android/util/cts/RationalTest.java
+++ b/tests/tests/util/src/android/util/cts/RationalTest.java
@@ -369,6 +369,34 @@
}
}
+ @SmallTest
+ public void testParseRational() {
+ assertEquals(new Rational(1, 2), Rational.parseRational("3:+6"));
+ assertEquals(new Rational(1, 2), Rational.parseRational("-3:-6"));
+ assertEquals(Rational.NaN, Rational.parseRational("NaN"));
+ assertEquals(Rational.POSITIVE_INFINITY, Rational.parseRational("Infinity"));
+ assertEquals(Rational.NEGATIVE_INFINITY, Rational.parseRational("-Infinity"));
+ assertEquals(Rational.ZERO, Rational.parseRational("0/261"));
+ assertEquals(Rational.NaN, Rational.parseRational("0/-0"));
+ assertEquals(Rational.POSITIVE_INFINITY, Rational.parseRational("1000/+0"));
+ assertEquals(Rational.NEGATIVE_INFINITY, Rational.parseRational("-1000/-0"));
+
+ try {
+ fail("Parsing " + Rational.parseRational("1.5") + " should not have succeeded");
+ } catch (NumberFormatException exception) {
+ // OK
+ }
+
+ try {
+ fail("Parsing " + Rational.parseRational("239") + " should not have succeeded");
+ } catch (NumberFormatException exception) {
+ // OK
+ }
+
+ Rational r = new Rational(10, 15);
+ assertEquals(r, Rational.parseRational(r.toString()));
+ }
+
private static void assertValueEquals(Rational object, float expected) {
assertEquals("Checking floatValue() for " + object + ";",
expected, object.floatValue());
diff --git a/tests/tests/util/src/android/util/cts/SizeTest.java b/tests/tests/util/src/android/util/cts/SizeTest.java
new file mode 100644
index 0000000..b0cc89b
--- /dev/null
+++ b/tests/tests/util/src/android/util/cts/SizeTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.util.cts;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Size;
+import android.util.SizeF;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SizeTest {
+ @Test
+ public void testConstructors() {
+ Size size = new Size(100, 200);
+ assertEquals(100, size.getWidth());
+ assertEquals(200, size.getHeight());
+
+ SizeF sizeF = new SizeF(100, 200);
+ assertEquals(100, sizeF.getWidth(), 0f);
+ assertEquals(200, sizeF.getHeight(), 0f);
+ }
+
+ @Test
+ public void testParseSize() {
+ try {
+ Size.parseSize("2by4");
+ fail("Should not be able to parse");
+ } catch (NumberFormatException ignored) {
+ }
+
+ assertEquals(new Size(100, 200), Size.parseSize("100*200"));
+ assertEquals(new Size(10, 20), Size.parseSize("10x20"));
+ assertEquals(new SizeF(9999, 9999), SizeF.parseSizeF("9999x9999"));
+ }
+
+ @Test
+ public void testParseSizeF() {
+ try {
+ SizeF.parseSizeF("2by4");
+ fail("Should not be able to parse");
+ } catch (NumberFormatException ignored) {
+ }
+
+ assertEquals(new SizeF(100f, 200f), SizeF.parseSizeF("100*200"));
+ assertEquals(new SizeF(10f, 20f), SizeF.parseSizeF("10x20"));
+ assertEquals(new SizeF(1000000f, 2.4f), SizeF.parseSizeF("1e6x2.4"));
+ }
+}
diff --git a/tests/tests/util/src/android/util/cts/TypedValueTest.java b/tests/tests/util/src/android/util/cts/TypedValueTest.java
index 2ab91d9..735074f 100644
--- a/tests/tests/util/src/android/util/cts/TypedValueTest.java
+++ b/tests/tests/util/src/android/util/cts/TypedValueTest.java
@@ -205,4 +205,24 @@
assertEquals(TypedValue.complexToDimension(10, dm), tv.getDimension(dm));
}
+
+ public void testGetComplexUnit() {
+ TypedValue tv = new TypedValue();
+ tv.data = 256;
+ assertEquals(TypedValue.COMPLEX_UNIT_PX, tv.getComplexUnit());
+ tv.data = 257;
+ assertEquals(TypedValue.COMPLEX_UNIT_DIP, tv.getComplexUnit());
+ tv.data = 258;
+ assertEquals(TypedValue.COMPLEX_UNIT_SP, tv.getComplexUnit());
+ tv.data = 259;
+ assertEquals(TypedValue.COMPLEX_UNIT_PT, tv.getComplexUnit());
+ tv.data = 260;
+ assertEquals(TypedValue.COMPLEX_UNIT_IN, tv.getComplexUnit());
+ tv.data = 261;
+ assertEquals(TypedValue.COMPLEX_UNIT_MM, tv.getComplexUnit());
+ tv.data = 21474864;
+ assertEquals(TypedValue.COMPLEX_UNIT_FRACTION, tv.getComplexUnit());
+ tv.data = 21474865;
+ assertEquals(TypedValue.COMPLEX_UNIT_FRACTION_PARENT, tv.getComplexUnit());
+ }
}
diff --git a/tests/tests/view/Android.mk b/tests/tests/view/Android.mk
index ba4be93..d6100c8 100644
--- a/tests/tests/view/Android.mk
+++ b/tests/tests/view/Android.mk
@@ -29,11 +29,12 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-test \
ctsdeviceutil \
ctstestrunner \
mockito-target \
- ub-uiautomator \
- android-support-test
+ platform-test-annotations \
+ ub-uiautomator
LOCAL_JNI_SHARED_LIBRARIES := libctsview_jni libnativehelper_compat_libc++
diff --git a/tests/tests/view/jni/Android.mk b/tests/tests/view/jni/Android.mk
index ac7b844..288e250 100644
--- a/tests/tests/view/jni/Android.mk
+++ b/tests/tests/view/jni/Android.mk
@@ -18,6 +18,8 @@
LOCAL_MODULE := libctsview_jni
+LOCAL_CFLAGS += -Werror
+
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := \
diff --git a/tests/tests/view/jni/CtsViewJniOnLoad.cpp b/tests/tests/view/jni/CtsViewJniOnLoad.cpp
index 2c1e643..1a7ef3c 100644
--- a/tests/tests/view/jni/CtsViewJniOnLoad.cpp
+++ b/tests/tests/view/jni/CtsViewJniOnLoad.cpp
@@ -16,8 +16,8 @@
*/
#include <jni.h>
-#include <utils/Log.h>
#define LOG_TAG "CtsViewJniOnLoad"
+#include <utils/Log.h>
extern int register_android_view_cts_ChoreographerNativeTest(JNIEnv* env);
diff --git a/tests/tests/view/src/android/view/cts/AbsSavedStateTest.java b/tests/tests/view/src/android/view/cts/AbsSavedStateTest.java
index 3662e2c..e4165bb 100644
--- a/tests/tests/view/src/android/view/cts/AbsSavedStateTest.java
+++ b/tests/tests/view/src/android/view/cts/AbsSavedStateTest.java
@@ -18,83 +18,128 @@
import android.os.Parcel;
import android.os.Parcelable;
+import android.support.test.filters.SmallTest;
import android.test.InstrumentationTestCase;
import android.view.AbsSavedState;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+@SmallTest
public class AbsSavedStateTest extends InstrumentationTestCase {
- // constant for test of writeToParcel
- public static final int TEST_NUMBER = 1;
-
public void testConstructor() {
- MockParcelable superState = new MockParcelable();
- assertNotNull(superState);
- new MockAbsSavedState(superState);
+ try {
+ new AbsSavedStateImpl((Parcelable) null);
+ fail("Expected NullPointerException");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ new AbsSavedStateImpl((Parcel) null);
+ fail("Expected NullPointerException");
+ } catch (NullPointerException e) {
+ // Expected.
+ }
+
+ try {
+ new AbsSavedStateImpl(null, null);
+ fail("Expected NullPointerException");
+ } catch (NullPointerException e) {
+ // Expected.
+ }
+
+ AbsSavedState superState = new AbsSavedStateImpl(Parcel.obtain());
+ assertNull(superState.getSuperState());
+
+ AbsSavedState s = new AbsSavedStateImpl(superState);
+ assertSame(superState, s.getSuperState());
Parcel source = Parcel.obtain();
- new MockAbsSavedState(source);
+ source.writeParcelable(superState, 0);
+ source.setDataPosition(0);
+ s = new AbsSavedStateImpl(source);
+ assertTrue(s.getSuperState() instanceof AbsSavedState);
- MockAbsSavedState savedState = new MockAbsSavedState(source);
- assertEquals(0, savedState.describeContents());
+ source = Parcel.obtain();
+ s = new AbsSavedStateImpl(source);
+ assertSame(AbsSavedState.EMPTY_STATE, s.getSuperState());
+
+ ClassLoader loader = AbsSavedState.class.getClassLoader();
+ source = Parcel.obtain();
+ source.writeParcelable(superState, 0);
+ source.setDataPosition(0);
+ s = new AbsSavedStateImpl(source, loader);
+ assertTrue(s.getSuperState() instanceof AbsSavedState);
+
+ source = Parcel.obtain();
+ s = new AbsSavedStateImpl(source, loader);
+ assertSame(AbsSavedState.EMPTY_STATE, s.getSuperState());
}
- public void testGetSuperState() {
- MockParcelable superState = new MockParcelable();
- assertNotNull(superState);
- MockAbsSavedState savedState = new MockAbsSavedState(superState);
+ public void testCreator() {
+ int size = 10;
+ AbsSavedState[] array = AbsSavedState.CREATOR.newArray(size);
+ assertNotNull(array);
+ assertEquals(size, array.length);
+ for (AbsSavedState state : array) {
+ assertNull(state);
+ }
- assertSame(superState, savedState.getSuperState());
+ AbsSavedState state = new AbsSavedStateImpl(AbsSavedState.EMPTY_STATE);
+ Parcel parcel = Parcel.obtain();
+ state.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ AbsSavedState unparceled = AbsSavedState.CREATOR.createFromParcel(parcel);
+ assertNotNull(unparceled);
+ assertEquals(AbsSavedState.EMPTY_STATE, unparceled.getSuperState());
+
+ AbsSavedState stateWithSuper = new AbsSavedStateImpl(state);
+ parcel = Parcel.obtain();
+ stateWithSuper.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ try {
+ AbsSavedState.CREATOR.createFromParcel(parcel);
+ fail("Expected IllegalStateException");
+ } catch (IllegalStateException e) {
+ // Expected.
+ }
}
public void testWriteToParcel() {
- MockParcelable superState = new MockParcelable();
- assertNotNull(superState);
- MockAbsSavedState savedState = new MockAbsSavedState(superState);
-
+ Parcelable superState = mock(Parcelable.class);
+ AbsSavedState savedState = new AbsSavedStateImpl(superState);
Parcel dest = Parcel.obtain();
int flags = 2;
savedState.writeToParcel(dest, flags);
-
- // we instantiate the writeToParcel of Parcalable
- // and give a return for test
- assertEquals(TEST_NUMBER, superState.writeToParcelRunSymbol());
- assertEquals(flags, superState.getFlags());
+ verify(superState).writeToParcel(eq(dest), eq(flags));
}
- static class MockAbsSavedState extends AbsSavedState {
-
- public MockAbsSavedState(Parcelable superState) {
+ private static class AbsSavedStateImpl extends AbsSavedState {
+ AbsSavedStateImpl(Parcelable superState) {
super(superState);
}
- public MockAbsSavedState(Parcel source) {
+ AbsSavedStateImpl(Parcel source) {
super(source);
}
- }
- static class MockParcelable implements Parcelable {
-
- // Test for writeToParcel
- private int mTest;
- private int mFlags;
-
- public int describeContents() {
- return 0;
+ AbsSavedStateImpl(Parcel source, ClassLoader loader) {
+ super(source, loader);
}
- // Instantiate writeToParcel
- public void writeToParcel(Parcel dest, int flags) {
- mTest = TEST_NUMBER;
- mFlags = flags;
- }
+ public static final Creator<AbsSavedStateImpl> CREATOR = new Creator<AbsSavedStateImpl>() {
+ @Override
+ public AbsSavedStateImpl createFromParcel(Parcel source) {
+ return new AbsSavedStateImpl(source);
+ }
- // For test of writeToParcel
- public int writeToParcelRunSymbol() {
- return mTest;
- }
-
- public int getFlags() {
- return mFlags;
- }
+ @Override
+ public AbsSavedStateImpl[] newArray(int size) {
+ return new AbsSavedStateImpl[size];
+ }
+ };
}
}
diff --git a/tests/tests/view/src/android/view/cts/NumberPickerTest.java b/tests/tests/view/src/android/view/cts/NumberPickerTest.java
deleted file mode 100644
index 2e2733e..0000000
--- a/tests/tests/view/src/android/view/cts/NumberPickerTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc.
- *
- * 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.
- */
-
-package android.view.cts;
-
-import android.test.AndroidTestCase;
-import android.widget.NumberPicker;
-
-public class NumberPickerTest extends AndroidTestCase {
-
- public void testSetDisplayedValues1() throws Exception {
- NumberPicker numberPicker = new NumberPicker(getContext());
- numberPicker.setMinValue(10);
- numberPicker.setMaxValue(12);
- numberPicker.setDisplayedValues(new String[]{"One", "Two", "Three"});
- }
-
- public void testSetDisplayedValues2() throws Exception {
- NumberPicker numberPicker = new NumberPicker(getContext());
- numberPicker.setMinValue(10);
- numberPicker.setMaxValue(14);
- try {
- numberPicker.setDisplayedValues(new String[]{"One", "Two", "Three"});
- fail("The size of the displayed values array must be equal to the selectable numbers!");
- } catch (Exception e) {
- /* expected */
- }
- }
-}
diff --git a/tests/tests/view/src/android/view/cts/ViewOutlineProviderTest.java b/tests/tests/view/src/android/view/cts/ViewOutlineProviderTest.java
new file mode 100644
index 0000000..bf21b30
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/ViewOutlineProviderTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.view.cts;
+
+import android.annotation.NonNull;
+import android.app.Activity;
+import android.graphics.Color;
+import android.graphics.Outline;
+import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ViewOutlineProviderTest {
+ @Rule
+ public ActivityTestRule mActivityTestRule = new ActivityTestRule<>(MockActivity.class);
+
+ Activity getActivity() { return mActivityTestRule.getActivity(); }
+
+ @Test
+ public void testBackground() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ View view = new View(mActivityTestRule.getActivity());
+ view.setLeftTopRightBottom(100, 200, 300, 400);
+
+
+ Outline outline = new Outline();
+ outline.setAlpha(1.0f);
+ Rect queryRect = new Rect();
+
+
+ // No background - outline is 0 alpha, width x height rect
+ ViewOutlineProvider.BACKGROUND.getOutline(view, outline);
+ outline.getRect(queryRect);
+ assertEquals(new Rect(0, 0, 200, 200), queryRect);
+ assertEquals(0f, outline.getAlpha(), 0f);
+
+
+ // With background - outline is passed directly from background
+ view.setBackground(new ColorDrawable(Color.BLACK) {
+ @Override
+ public void getOutline(@NonNull Outline outline) {
+ outline.setRect(1, 2, 3, 4);
+ outline.setAlpha(0.123f);
+ }
+ });
+ ViewOutlineProvider.BACKGROUND.getOutline(view, outline);
+ outline.getRect(queryRect);
+ assertEquals(new Rect(1, 2, 3, 4), queryRect);
+ assertEquals(0.123f, outline.getAlpha(), 0f);
+ });
+ }
+
+
+ @Test
+ public void testBounds() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ View view = new View(mActivityTestRule.getActivity());
+
+ Outline outline = new Outline();
+ Rect queryRect = new Rect();
+ outline.setAlpha(0.123f);
+
+ view.setLeftTopRightBottom(1, 2, 3, 4);
+ ViewOutlineProvider.BOUNDS.getOutline(view, outline);
+ outline.getRect(queryRect);
+ assertEquals(new Rect(0, 0, 2, 2), queryRect); // local width/height
+ assertEquals(0.123f, outline.getAlpha(), 0f); // alpha not changed
+
+ view.setLeftTopRightBottom(100, 200, 300, 400);
+ ViewOutlineProvider.BOUNDS.getOutline(view, outline);
+ outline.getRect(queryRect);
+ assertEquals(new Rect(0, 0, 200, 200), queryRect); // local width/height
+ assertEquals(0.123f, outline.getAlpha(), 0f); // alpha not changed
+ });
+ }
+
+ @Test
+ public void testPaddedBounds() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ View view = new View(mActivityTestRule.getActivity());
+
+ Outline outline = new Outline();
+ Rect queryRect = new Rect();
+ outline.setAlpha(0.123f);
+
+ view.setLeftTopRightBottom(10, 20, 30, 40);
+ view.setPadding(0, 0, 0, 0);
+ ViewOutlineProvider.PADDED_BOUNDS.getOutline(view, outline);
+ outline.getRect(queryRect);
+ assertEquals(new Rect(0, 0, 20, 20), queryRect); // local width/height
+ assertEquals(0.123f, outline.getAlpha(), 0f); // alpha not changed
+
+ view.setPadding(5, 5, 5, 5);
+ ViewOutlineProvider.PADDED_BOUNDS.getOutline(view, outline);
+ outline.getRect(queryRect);
+ assertEquals(new Rect(5, 5, 15, 15), queryRect); // local width/height, inset by 5
+ assertEquals(0.123f, outline.getAlpha(), 0f); // alpha not changed
+ });
+ }
+}
diff --git a/tests/tests/view/src/android/view/cts/View_BaseSavedStateTest.java b/tests/tests/view/src/android/view/cts/View_BaseSavedStateTest.java
index ce64a18..8ce70f2 100644
--- a/tests/tests/view/src/android/view/cts/View_BaseSavedStateTest.java
+++ b/tests/tests/view/src/android/view/cts/View_BaseSavedStateTest.java
@@ -16,15 +16,86 @@
package android.view.cts;
-
import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.test.filters.SmallTest;
import android.test.InstrumentationTestCase;
+import android.view.AbsSavedState;
import android.view.View.BaseSavedState;
-public class View_BaseSavedStateTest extends InstrumentationTestCase {
- public void testConstructors() {
- BaseSavedState state = new BaseSavedState(Parcel.obtain());
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
- new BaseSavedState(state);
+@SmallTest
+public class View_BaseSavedStateTest extends InstrumentationTestCase {
+
+ public void testConstructors() {
+ try {
+ new BaseSavedState((Parcelable) null);
+ fail("Expected NullPointerException");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ new BaseSavedState((Parcel) null);
+ fail("Expected NullPointerException");
+ } catch (NullPointerException e) {
+ // Expected.
+ }
+
+ try {
+ new BaseSavedState(null, null);
+ fail("Expected NullPointerException");
+ } catch (NullPointerException e) {
+ // Expected.
+ }
+
+ BaseSavedState superState = new BaseSavedState(Parcel.obtain());
+ assertEquals(AbsSavedState.EMPTY_STATE, superState.getSuperState());
+
+ BaseSavedState s = new BaseSavedState(superState);
+ assertEquals(superState, s.getSuperState());
+
+ Parcel source = Parcel.obtain();
+ source.writeParcelable(superState, 0);
+ source.setDataPosition(0);
+ s = new BaseSavedState(source);
+ assertTrue(s.getSuperState() instanceof BaseSavedState);
+
+ ClassLoader loader = BaseSavedState.class.getClassLoader();
+ source = Parcel.obtain();
+ source.writeParcelable(superState, 0);
+ source.setDataPosition(0);
+ s = new BaseSavedState(source, loader);
+ assertTrue(s.getSuperState() instanceof BaseSavedState);
+ }
+
+ public void testCreator() {
+ int size = 10;
+ BaseSavedState[] array = BaseSavedState.CREATOR.newArray(size);
+ assertNotNull(array);
+ assertEquals(size, array.length);
+ for (BaseSavedState state : array) {
+ assertNull(state);
+ }
+
+ BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
+ Parcel parcel = Parcel.obtain();
+ state.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ BaseSavedState unparceled = BaseSavedState.CREATOR.createFromParcel(parcel);
+ assertNotNull(unparceled);
+ assertEquals(AbsSavedState.EMPTY_STATE, unparceled.getSuperState());
+ }
+
+ public void testWriteToParcel() {
+ Parcelable superState = mock(Parcelable.class);
+ BaseSavedState savedState = new BaseSavedState(superState);
+ Parcel dest = Parcel.obtain();
+ int flags = 2;
+ savedState.writeToParcel(dest, flags);
+ verify(superState).writeToParcel(eq(dest), eq(flags));
}
}
diff --git a/tests/tests/widget/Android.mk b/tests/tests/widget/Android.mk
index 4bc9eee..3d4cead 100644
--- a/tests/tests/widget/Android.mk
+++ b/tests/tests/widget/Android.mk
@@ -22,10 +22,12 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_STATIC_JAVA_LIBRARIES += \
+ android-support-test \
mockito-target \
android-common \
ctsdeviceutil \
- ctstestrunner
+ ctstestrunner \
+ platform-test-annotations
LOCAL_JAVA_LIBRARIES := android.test.runner
diff --git a/tests/tests/widget/AndroidManifest.xml b/tests/tests/widget/AndroidManifest.xml
index 224966d..c200799 100644
--- a/tests/tests/widget/AndroidManifest.xml
+++ b/tests/tests/widget/AndroidManifest.xml
@@ -92,9 +92,25 @@
</intent-filter>
</activity>
+ <activity android:name="android.widget.cts.SpinnerCtsActivity"
+ android:label="SpinnerCtsActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
<activity android:name="android.widget.cts.ToolbarCtsActivity"
- android:theme="@android:style/Theme.Material.Light.NoActionBar"
- android:label="ToolbarCtsActivity">
+ android:theme="@android:style/Theme.Material.Light.NoActionBar"
+ android:label="ToolbarCtsActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.widget.cts.ActionMenuViewCtsActivity"
+ android:label="ActionMenuViewCtsActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
@@ -149,6 +165,14 @@
</intent-filter>
</activity>
+ <activity android:name="android.widget.cts.AbsSeekBarCtsActivity"
+ android:label="AbsSeekBarCtsActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
<activity android:name="android.widget.cts.ProgressBarCtsActivity"
android:label="ProgressBarCtsActivity">
<intent-filter>
@@ -189,8 +213,16 @@
</intent-filter>
</activity>
- <activity android:name="android.widget.cts.ExpandableListSimple"
- android:label="ExpandableListSimple">
+ <activity android:name="android.widget.cts.ExpandableListBasic"
+ android:label="ExpandableListBasic">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.widget.cts.ExpandableList"
+ android:label="ExpandableList">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
@@ -388,6 +420,70 @@
</intent-filter>
</activity>
+ <activity android:name="android.widget.cts.DatePickerCtsActivity"
+ android:label="DatePickerCtsActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.widget.cts.SearchViewCtsActivity"
+ android:label="SearchViewCtsActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.widget.cts.ImageButtonCtsActivity"
+ android:label="ImageButtonCtsActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.widget.cts.NumberPickerCtsActivity"
+ android:label="NumberPickerCtsActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.widget.cts.CheckBoxCtsActivity"
+ android:label="CheckBoxCtsActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.widget.cts.RadioButtonCtsActivity"
+ android:label="RadioButtonCtsActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.widget.cts.ToggleButtonCtsActivity"
+ android:label="ToggleButtonCtsActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.widget.cts.TimePickerCtsActivity"
+ android:label="TimePickerCtsActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
<activity android:name="android.app.ActivityGroup"
android:label="ActivityGroup" />
diff --git a/tests/tests/widget/res/drawable/blue_fill.xml b/tests/tests/widget/res/drawable/blue_fill.xml
index 5a24f08..383e7db 100644
--- a/tests/tests/widget/res/drawable/blue_fill.xml
+++ b/tests/tests/widget/res/drawable/blue_fill.xml
@@ -17,5 +17,5 @@
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
- <solid android:color="#0000FF" />
+ <solid android:color="#00F" />
</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/green_fill.xml b/tests/tests/widget/res/drawable/green_fill.xml
new file mode 100644
index 0000000..76c1101
--- /dev/null
+++ b/tests/tests/widget/res/drawable/green_fill.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="#0F0" />
+</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/linear_layout_divider_magenta.xml b/tests/tests/widget/res/drawable/linear_layout_divider_magenta.xml
new file mode 100644
index 0000000..2dbd654
--- /dev/null
+++ b/tests/tests/widget/res/drawable/linear_layout_divider_magenta.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid
+ android:color="#F0F" />
+ <size
+ android:width="@dimen/linear_layout_divider_size"
+ android:height="@dimen/linear_layout_divider_size" />
+</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/linear_layout_divider_red.xml b/tests/tests/widget/res/drawable/linear_layout_divider_red.xml
new file mode 100644
index 0000000..56e88ef
--- /dev/null
+++ b/tests/tests/widget/res/drawable/linear_layout_divider_red.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid
+ android:color="#F00" />
+ <size
+ android:width="@dimen/linear_layout_divider_size"
+ android:height="@dimen/linear_layout_divider_size" />
+</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/magenta_fill.xml b/tests/tests/widget/res/drawable/magenta_fill.xml
index cbb594f..8b6da76 100644
--- a/tests/tests/widget/res/drawable/magenta_fill.xml
+++ b/tests/tests/widget/res/drawable/magenta_fill.xml
@@ -17,5 +17,5 @@
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
- <solid android:color="#FF00FF" />
+ <solid android:color="#F0F" />
</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/red_fill.xml b/tests/tests/widget/res/drawable/red_fill.xml
index e443240..8baf5b6 100644
--- a/tests/tests/widget/res/drawable/red_fill.xml
+++ b/tests/tests/widget/res/drawable/red_fill.xml
@@ -17,5 +17,5 @@
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
- <solid android:color="#8F00" />
+ <solid android:color="#F00" />
</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/red_translucent_fill.xml b/tests/tests/widget/res/drawable/red_translucent_fill.xml
new file mode 100644
index 0000000..edfbfa0
--- /dev/null
+++ b/tests/tests/widget/res/drawable/red_translucent_fill.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="#80FF0000" />
+</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/drawable/yellow_fill.xml b/tests/tests/widget/res/drawable/yellow_fill.xml
index 3bd80977..44f88c4 100644
--- a/tests/tests/widget/res/drawable/yellow_fill.xml
+++ b/tests/tests/widget/res/drawable/yellow_fill.xml
@@ -17,5 +17,5 @@
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
- <solid android:color="#FFFF00" />
+ <solid android:color="#FF0" />
</shape>
\ No newline at end of file
diff --git a/tests/tests/widget/res/layout/actionmenuview_layout.xml b/tests/tests/widget/res/layout/actionmenuview_layout.xml
new file mode 100644
index 0000000..5d2895e
--- /dev/null
+++ b/tests/tests/widget/res/layout/actionmenuview_layout.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/button" />
+
+ <ActionMenuView
+ android:id="@+id/action_menu_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+</LinearLayout>
+
diff --git a/tests/tests/widget/res/layout/autocompletetextview_layout.xml b/tests/tests/widget/res/layout/autocompletetextview_layout.xml
index 27eccab..8e023a1 100644
--- a/tests/tests/widget/res/layout/autocompletetextview_layout.xml
+++ b/tests/tests/widget/res/layout/autocompletetextview_layout.xml
@@ -24,10 +24,11 @@
android:layout_height="wrap_content"
android:text="@string/notify" />
- <android.widget.cts.AutoCompleteTextViewNoIme android:id="@+id/autocompletetv_edit"
- android:completionThreshold="1"
- android:completionHint="@string/tabs_1"
+ <android.widget.cts.AutoCompleteTextViewNoIme
+ android:id="@+id/autocompletetv_edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:completionThreshold="1"
+ android:completionHint="@string/tabs_1"
android:inputType="none"/>
</LinearLayout>
diff --git a/tests/tests/widget/res/layout/calendarview_layout.xml b/tests/tests/widget/res/layout/calendarview_layout.xml
index 3bc5e47..507d48e 100644
--- a/tests/tests/widget/res/layout/calendarview_layout.xml
+++ b/tests/tests/widget/res/layout/calendarview_layout.xml
@@ -17,6 +17,7 @@
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/scroller"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
diff --git a/tests/tests/widget/res/layout/checkbox_layout.xml b/tests/tests/widget/res/layout/checkbox_layout.xml
index a1f1718..c922436 100644
--- a/tests/tests/widget/res/layout/checkbox_layout.xml
+++ b/tests/tests/widget/res/layout/checkbox_layout.xml
@@ -14,12 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
- <CheckBox android:id="@+id/check_box"
+ <CheckBox
+ android:id="@+id/check_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
diff --git a/tests/tests/widget/res/layout/checkedtextview_layout.xml b/tests/tests/widget/res/layout/checkedtextview_layout.xml
index d5b9c1f..fbee93e 100644
--- a/tests/tests/widget/res/layout/checkedtextview_layout.xml
+++ b/tests/tests/widget/res/layout/checkedtextview_layout.xml
@@ -14,20 +14,22 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
- <ListView android:id="@+id/checkedtextview_listview"
- android:orientation="vertical"
+ <ListView
+ android:id="@+id/checkedtextview_listview"
android:layout_width="match_parent"
- android:layout_height="match_parent">
- </ListView>
+ android:layout_height="0dip"
+ android:layout_weight="1" />
- <CheckedTextView android:id="@+id/checkedtextview_test"
- android:orientation="vertical"
+ <CheckedTextView
+ android:id="@+id/checkedtextview_test"
android:layout_width="match_parent"
- android:layout_height="match_parent">
- </CheckedTextView>
+ android:layout_height="wrap_content"
+ android:text="@string/hello_world" />
</LinearLayout>
diff --git a/tests/tests/widget/res/layout/datepicker_layout.xml b/tests/tests/widget/res/layout/datepicker_layout.xml
index 925674c..9857440 100644
--- a/tests/tests/widget/res/layout/datepicker_layout.xml
+++ b/tests/tests/widget/res/layout/datepicker_layout.xml
@@ -14,14 +14,29 @@
limitations under the License.
-->
-<RelativeLayout
+<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent">
- <DatePicker
- android:id="@+id/datePicker_dp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true" />
+ android:layout_height="match_parent"
+ android:fillViewport="true">
-</RelativeLayout>
+ <LinearLayout
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <DatePicker
+ android:id="@+id/date_picker_calendar_mode"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:datePickerMode="calendar" />
+
+ <DatePicker
+ android:id="@+id/date_picker_spinner_mode"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:datePickerMode="spinner" />
+
+ </LinearLayout>
+</ScrollView>
diff --git a/tests/tests/widget/res/layout/expandablelistview_child.xml b/tests/tests/widget/res/layout/expandablelistview_child.xml
new file mode 100644
index 0000000..b34f10b
--- /dev/null
+++ b/tests/tests/widget/res/layout/expandablelistview_child.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textSize="18sp" />
diff --git a/tests/tests/widget/res/layout/expandablelistview_group.xml b/tests/tests/widget/res/layout/expandablelistview_group.xml
new file mode 100644
index 0000000..be929ee
--- /dev/null
+++ b/tests/tests/widget/res/layout/expandablelistview_group.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textStyle="bold"
+ android:textSize="24sp" />
diff --git a/tests/tests/widget/res/layout/imagebutton_layout.xml b/tests/tests/widget/res/layout/imagebutton_layout.xml
new file mode 100644
index 0000000..f59f669
--- /dev/null
+++ b/tests/tests/widget/res/layout/imagebutton_layout.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <ImageButton
+ android:id="@+id/image_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/icon_red" />
+
+</LinearLayout>
diff --git a/tests/tests/widget/res/layout/imagebutton_test.xml b/tests/tests/widget/res/layout/imagebutton_test.xml
deleted file mode 100644
index 7d4b691..0000000
--- a/tests/tests/widget/res/layout/imagebutton_test.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2008 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.
- -->
-<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/imagebutton"
- android:layout_width="96px"
- android:layout_height="76px"
- android:soundEffectsEnabled="false"
-/>
-
diff --git a/tests/tests/widget/res/layout/linearlayout_layout.xml b/tests/tests/widget/res/layout/linearlayout_layout.xml
index 8881552..11d2a71 100644
--- a/tests/tests/widget/res/layout/linearlayout_layout.xml
+++ b/tests/tests/widget/res/layout/linearlayout_layout.xml
@@ -14,125 +14,228 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/linearlayout_root"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/linearlayout_root"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
- <LinearLayout android:id="@+id/horizontal"
- android:orientation="horizontal"
+ <LinearLayout
+ android:id="@+id/horizontal"
android:layout_width="wrap_content"
android:layout_height="100dip"
- android:background="#FF909090">
+ android:orientation="horizontal"
+ android:background="#888">
- <TextView android:id="@+id/gravity_top"
- android:background="#FF00FF00"
+ <TextView
+ android:id="@+id/gravity_top"
android:layout_width="wrap_content"
android:layout_height="50dip"
android:layout_gravity="top"
- android:text="@string/horizontal_text_1"/>
+ android:background="#0F0"
+ android:text="@string/horizontal_text_1" />
- <TextView android:id="@+id/gravity_center_vertical"
- android:background="#FF00FF00"
+ <TextView
+ android:id="@+id/gravity_center_vertical"
android:layout_width="wrap_content"
android:layout_height="50dip"
android:layout_gravity="center_vertical"
- android:text="@string/horizontal_text_2"/>
+ android:background="#0F0"
+ android:text="@string/horizontal_text_2" />
- <TextView android:id="@+id/gravity_bottom"
- android:background="#FF00FF00"
+ <TextView
+ android:id="@+id/gravity_bottom"
android:layout_width="wrap_content"
android:layout_height="50dip"
android:layout_gravity="bottom"
- android:text="@string/horizontal_text_3"/>
+ android:background="#0F0"
+ android:text="@string/horizontal_text_3" />
</LinearLayout>
- <LinearLayout android:id="@+id/vertical"
- android:orientation="vertical"
+ <LinearLayout
+ android:id="@+id/vertical"
android:layout_width="100dip"
android:layout_height="wrap_content"
- android:background="#FFFF0909">
+ android:orientation="vertical"
+ android:background="#F00">
- <TextView android:id="@+id/gravity_left"
- android:background="#FF00FF00"
+ <TextView
+ android:id="@+id/gravity_left"
android:layout_width="wrap_content"
android:layout_height="20dip"
android:layout_gravity="left"
- android:text="@string/vertical_text_1"/>
+ android:background="#0F0"
+ android:text="@string/vertical_text_1" />
- <TextView android:id="@+id/gravity_center_horizontal"
- android:background="#FF0000FF"
+ <TextView
+ android:id="@+id/gravity_center_horizontal"
android:layout_width="wrap_content"
android:layout_height="20dip"
android:layout_gravity="center_horizontal"
- android:text="@string/vertical_text_2"/>
+ android:background="#00F"
+ android:text="@string/vertical_text_2" />
- <TextView android:id="@+id/gravity_right"
- android:background="#FF00FF00"
+ <TextView
+ android:id="@+id/gravity_right"
android:layout_width="wrap_content"
android:layout_height="20dip"
android:layout_gravity="right"
- android:text="@string/vertical_text_3"/>
+ android:background="#0F0"
+ android:text="@string/vertical_text_3" />
</LinearLayout>
- <LinearLayout android:id="@+id/weightsum"
+ <LinearLayout
+ android:id="@+id/weightsum"
+ android:layout_width="100dip"
+ android:layout_height="100dip"
android:orientation="horizontal"
android:weightSum="1.0"
android:baselineAligned="false"
- android:layout_width="100dip"
- android:layout_height="100dip"
- android:background="#FF909090">
+ android:background="#888">
- <TextView android:id="@+id/weight_0_2"
- android:background="#FF0000FF"
+ <TextView
+ android:id="@+id/weight_0_2"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0.2"
- android:text="@string/horizontal_text_1"/>
+ android:background="#00F"
+ android:text="@string/horizontal_text_1" />
- <TextView android:id="@+id/weight_0_5"
- android:background="#FFF00F0F"
+ <TextView
+ android:id="@+id/weight_0_5"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0.5"
- android:text="@string/horizontal_text_2"/>
+ android:background="#F00"
+ android:text="@string/horizontal_text_2" />
- <TextView android:id="@+id/weight_0_3"
- android:background="#FF0000FF"
+ <TextView
+ android:id="@+id/weight_0_3"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0.3"
- android:text="@string/horizontal_text_3"/>
+ android:background="#00F"
+ android:text="@string/horizontal_text_3" />
</LinearLayout>
- <LinearLayout android:id="@+id/baseline_aligned_child_index"
+ <LinearLayout
+ android:id="@+id/weightsum_vertical"
+ android:layout_width="100dip"
+ android:layout_height="100dip"
android:orientation="vertical"
- android:baselineAlignedChildIndex="1"
+ android:weightSum="1.0"
+ android:baselineAligned="false"
+ android:background="#888">
+
+ <TextView
+ android:id="@+id/weight_0_1"
+ android:layout_width="wrap_content"
+ android:layout_height="0dip"
+ android:layout_weight="0.1"
+ android:background="#00F"
+ android:text="@string/vertical_text_1" />
+
+ <TextView
+ android:id="@+id/weight_0_4"
+ android:layout_width="wrap_content"
+ android:layout_height="0dip"
+ android:layout_weight="0.4"
+ android:background="#F00"
+ android:text="@string/vertical_text_2" />
+
+ <TextView
+ android:id="@+id/weight_0_5"
+ android:layout_width="wrap_content"
+ android:layout_height="0dip"
+ android:layout_weight="0.5"
+ android:background="#00F"
+ android:text="@string/vertical_text_3" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/baseline_aligned_child_index"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:background="#FFFF0909">
+ android:orientation="vertical"
+ android:baselineAlignedChildIndex="1"
+ android:background="#F00">
- <TextView android:id="@+id/textview1"
- android:background="#FF00FF00"
+ <TextView
+ android:id="@+id/textview1"
android:layout_width="wrap_content"
android:layout_height="20dip"
android:layout_gravity="left"
- android:text="@string/vertical_text_1"/>
+ android:background="#0F0"
+ android:text="@string/vertical_text_1" />
- <TextView android:id="@+id/textview2"
- android:background="#FF0000FF"
+ <TextView
+ android:id="@+id/textview2"
android:layout_width="wrap_content"
android:layout_height="20dip"
android:layout_gravity="center_horizontal"
- android:text="@string/vertical_text_2"/>
+ android:background="#00F"
+ android:text="@string/vertical_text_2" />
- <TextView android:id="@+id/textview3"
- android:background="#FF00FF00"
+ <TextView
+ android:id="@+id/textview3"
android:layout_width="wrap_content"
android:layout_height="20dip"
android:layout_gravity="right"
- android:text="@string/vertical_text_3"/>
+ android:background="#0F0"
+ android:text="@string/vertical_text_3" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/vertical_with_divider"
+ android:layout_width="100px"
+ android:layout_height="100px"
+ android:orientation="vertical"
+ android:background="#FF0"
+ android:showDividers="middle"
+ android:divider="@drawable/linear_layout_divider_red"
+ android:dividerPadding="@dimen/linear_layout_divider_padding">
+
+ <View
+ android:id="@+id/child1"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="0.5"
+ android:background="#00F" />
+
+ <View
+ android:id="@+id/child2"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="0.5"
+ android:background="#0F0" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/horizontal_with_divider"
+ android:layout_width="100px"
+ android:layout_height="100px"
+ android:orientation="horizontal"
+ android:background="#FF0"
+ android:showDividers="middle"
+ android:divider="@drawable/linear_layout_divider_red"
+ android:dividerPadding="@dimen/linear_layout_divider_padding">
+
+ <View
+ android:id="@+id/child1"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="0.5"
+ android:background="#00F" />
+
+ <View
+ android:id="@+id/child2"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="0.5"
+ android:background="#0F0" />
+
</LinearLayout>
</LinearLayout>
diff --git a/tests/tests/widget/res/layout/numberpicker_layout.xml b/tests/tests/widget/res/layout/numberpicker_layout.xml
new file mode 100644
index 0000000..2e370d8
--- /dev/null
+++ b/tests/tests/widget/res/layout/numberpicker_layout.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2016 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
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <NumberPicker
+ android:id="@+id/number_picker"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/widget/res/layout/progressbar_layout.xml b/tests/tests/widget/res/layout/progressbar_layout.xml
index a1786b8..f242135 100644
--- a/tests/tests/widget/res/layout/progressbar_layout.xml
+++ b/tests/tests/widget/res/layout/progressbar_layout.xml
@@ -14,28 +14,47 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:fillViewport="true">
- <ProgressBar
- android:id="@+id/progress_tint"
- android:progressTint="@android:color/white"
- android:progressTintMode="src_over"
- android:progressBackgroundTint="@android:color/white"
- android:progressBackgroundTintMode="src_over"
- android:secondaryProgressTint="@android:color/white"
- android:secondaryProgressTintMode="src_over"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- style="@android:style/Widget.ProgressBar.Horizontal" />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
- <ProgressBar
- android:id="@+id/indeterminate_tint"
- android:indeterminateTint="@android:color/white"
- android:indeterminateTintMode="src_over"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- style="@android:style/Widget.ProgressBar.Large" />
+ <ProgressBar
+ style="@android:style/Widget.Material.Light.ProgressBar"
+ android:id="@+id/progress"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
-</LinearLayout>
+ <ProgressBar
+ style="@android:style/Widget.Material.Light.ProgressBar.Horizontal"
+ android:id="@+id/progress_horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <ProgressBar
+ style="@android:style/Widget.Material.Light.ProgressBar.Horizontal"
+ android:id="@+id/progress_tint"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:progressTint="@android:color/white"
+ android:progressTintMode="src_over"
+ android:progressBackgroundTint="@android:color/white"
+ android:progressBackgroundTintMode="src_over"
+ android:secondaryProgressTint="@android:color/white"
+ android:secondaryProgressTintMode="src_over" />
+
+ <ProgressBar
+ style="@android:style/Widget.Material.Light.ProgressBar.Large"
+ android:id="@+id/indeterminate_tint"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:indeterminateTint="@android:color/white"
+ android:indeterminateTintMode="src_over" />
+
+ </LinearLayout>
+</ScrollView>
\ No newline at end of file
diff --git a/tests/tests/widget/res/layout/radiobutton_layout.xml b/tests/tests/widget/res/layout/radiobutton_layout.xml
new file mode 100644
index 0000000..23c1839
--- /dev/null
+++ b/tests/tests/widget/res/layout/radiobutton_layout.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <RadioButton
+ android:id="@+id/radio_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/hello_world" />
+
+</LinearLayout>
diff --git a/tests/tests/widget/res/layout/ratingbar_layout.xml b/tests/tests/widget/res/layout/ratingbar_layout.xml
index acc7fa8..b2fb4c7 100644
--- a/tests/tests/widget/res/layout/ratingbar_layout.xml
+++ b/tests/tests/widget/res/layout/ratingbar_layout.xml
@@ -14,18 +14,19 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
- <RatingBar android:id="@+id/ratingbar_constructor"
+ <RatingBar
+ android:id="@+id/ratingbar_constructor"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:isIndicator="false"
android:numStars="50"
android:rating="1.2"
- android:stepSize="0.2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"/>
+ android:stepSize="0.2" />
</LinearLayout>
diff --git a/tests/tests/widget/res/layout/remoteviews_good.xml b/tests/tests/widget/res/layout/remoteviews_good.xml
index 8fdbc64..1db2157 100644
--- a/tests/tests/widget/res/layout/remoteviews_good.xml
+++ b/tests/tests/widget/res/layout/remoteviews_good.xml
@@ -14,42 +14,56 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/remoteViews_good"
- android:orientation="vertical"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
- <LinearLayout android:id="@+id/remoteView_linear"
+ <LinearLayout
+ android:id="@+id/remoteView_linear"
android:layout_width="10dip"
android:layout_height="10dip" />
- <TextView android:id="@+id/remoteView_text"
+ <TextView
+ android:id="@+id/remoteView_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
- <ImageView android:id="@+id/remoteView_image"
+ <ImageView
+ android:id="@+id/remoteView_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
- <FrameLayout android:id="@+id/remoteView_frame"
+ <FrameLayout
+ android:id="@+id/remoteView_frame"
android:layout_width="10dip"
android:layout_height="10dip" />
- <RelativeLayout android:id="@+id/remoteView_relative"
+ <RelativeLayout
+ android:id="@+id/remoteView_relative"
android:layout_width="10dip"
android:layout_height="10dip" />
- <AbsoluteLayout android:id="@+id/remoteView_absolute"
+ <AbsoluteLayout
+ android:id="@+id/remoteView_absolute"
android:layout_width="10dip"
android:layout_height="10dip" />
- <ProgressBar android:id="@+id/remoteView_progress"
+ <ProgressBar
+ android:id="@+id/remoteView_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal" />
- <Chronometer android:id="@+id/remoteView_chronometer"
+ <Chronometer
+ android:id="@+id/remoteView_chronometer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <android.widget.cts.MyRemotableView
+ android:id="@+id/remoteView_custom"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
diff --git a/tests/tests/widget/res/layout/searchview_layout.xml b/tests/tests/widget/res/layout/searchview_layout.xml
new file mode 100644
index 0000000..b8705e0
--- /dev/null
+++ b/tests/tests/widget/res/layout/searchview_layout.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2016 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
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <SearchView
+ android:id="@+id/search_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <SearchView
+ android:id="@+id/search_view_with_defaults"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:maxWidth="@dimen/search_view_max_width"
+ android:iconifiedByDefault="false"
+ android:queryHint="@string/search_query_hint"
+ android:inputType="textCapCharacters"
+ android:imeOptions="actionDone" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/widget/res/layout/searchview_suggestion_item.xml b/tests/tests/widget/res/layout/searchview_suggestion_item.xml
new file mode 100644
index 0000000..91f02f5
--- /dev/null
+++ b/tests/tests/widget/res/layout/searchview_suggestion_item.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/search_view_suggestion_row_height"
+ android:textAppearance="?android:attr/textAppearanceListItemSmall"
+ android:gravity="center_vertical"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" />
diff --git a/tests/tests/widget/res/layout/simple_spinner_item_layout.xml b/tests/tests/widget/res/layout/simple_spinner_item_layout.xml
new file mode 100644
index 0000000..512b138
--- /dev/null
+++ b/tests/tests/widget/res/layout/simple_spinner_item_layout.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/text1"
+ style="?android:attr/spinnerItemStyle"
+ android:singleLine="true"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:ellipsize="marquee"
+ android:textAlignment="inherit"/>
diff --git a/tests/tests/widget/res/layout/spinner_layout.xml b/tests/tests/widget/res/layout/spinner_layout.xml
new file mode 100644
index 0000000..43a6411
--- /dev/null
+++ b/tests/tests/widget/res/layout/spinner_layout.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="true">
+
+ <LinearLayout
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <Spinner
+ android:id="@+id/spinner_dropdown_mode"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:spinnerMode="dropdown"
+ android:prompt="@string/text_view_hello" />
+
+ <Spinner
+ android:id="@+id/spinner_dialog_mode"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:spinnerMode="dialog"
+ android:prompt="@string/text_view_hello" />
+
+ </LinearLayout>
+</ScrollView>
diff --git a/tests/tests/widget/res/layout/switch_layout.xml b/tests/tests/widget/res/layout/switch_layout.xml
index 12e10d2..880c6df 100644
--- a/tests/tests/widget/res/layout/switch_layout.xml
+++ b/tests/tests/widget/res/layout/switch_layout.xml
@@ -15,11 +15,31 @@
~ limitations under the License
-->
-<Switch xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/switch_view"
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <Switch
+ android:id="@+id/switch1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:thumbTint="@android:color/white"
android:thumbTintMode="src_over"
android:trackTint="@android:color/black"
android:trackTintMode="src_atop" />
+
+ <Switch
+ android:id="@+id/switch2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:thumb="@drawable/icon_blue"
+ android:track="@drawable/red_translucent_fill" />
+
+ <Switch
+ android:id="@+id/switch3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/widget/res/layout/textview_layout.xml b/tests/tests/widget/res/layout/textview_layout.xml
index e3144eb..87ceac1 100644
--- a/tests/tests/widget/res/layout/textview_layout.xml
+++ b/tests/tests/widget/res/layout/textview_layout.xml
@@ -14,209 +14,264 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:id="@+id/layout_textviewtest">
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/scroller"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="true">
- <ScrollView android:layout_width="match_parent"
- android:layout_height="match_parent">
+ <LinearLayout
+ android:id="@+id/layout_textviewtest"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
- <LinearLayout android:orientation="vertical"
+ <TextView
+ android:id="@+id/textview_textAttr"
+ android:fontFamily="@null"
+ android:text="@string/text_view_hello"
+ android:textColor="@drawable/black"
+ android:textColorHighlight="@drawable/yellow"
+ android:textColorHint="@drawable/red"
+ android:textColorLink="@drawable/blue"
+ android:textScaleX="1.2"
+ android:typeface="normal"
+ android:textSize="20px"
+ android:textStyle="normal"
+ android:textAppearance="@null"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <TextView
+ android:id="@+id/textview_password"
+ android:password="true"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <TextView
+ android:id="@+id/textview_singleLine"
+ android:singleLine="true"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <TextView
+ android:id="@+id/textview_text"
+ android:text="@string/text_view_hello"
+ android:breakStrategy="simple"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <TextView
+ android:id="@+id/textview_text_two_lines"
+ android:text="@string/text_view_hello_two_lines"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <android.widget.cts.MockTextView
+ android:id="@+id/mock_textview_left"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:requiresFadingEdge="horizontal"
+ android:singleLine="true"
+ android:text="@string/long_text"
+ android:gravity="left" />
+
+ <android.widget.cts.MockTextView
+ android:id="@+id/mock_textview_right"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:requiresFadingEdge="horizontal"
+ android:singleLine="true"
+ android:text="@string/long_text"
+ android:gravity="right" />
+
+ <android.widget.cts.MockTextView
+ android:id="@+id/mock_textview_center"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:requiresFadingEdge="horizontal"
+ android:singleLine="true"
+ android:text="@string/long_text"
+ android:gravity="center" />
+
+ <TextView
+ android:id="@+id/textview_ltr"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+
+ <TextView
+ android:id="@+id/textview_rtl"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+
+ <TextView
+ android:id="@+id/textview_drawable_1_1"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:drawableLeft="@drawable/icon_blue"
+ android:drawableRight="@drawable/icon_red"
+ android:drawableTop="@drawable/icon_green"
+ android:drawableBottom="@drawable/icon_yellow"
+ android:layoutDirection="ltr" />
+
+ <TextView
+ android:id="@+id/textview_drawable_1_2"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:drawableLeft="@drawable/icon_blue"
+ android:drawableRight="@drawable/icon_red"
+ android:drawableTop="@drawable/icon_green"
+ android:drawableBottom="@drawable/icon_yellow"
+ android:layoutDirection="rtl" />
+
+ <TextView
+ android:id="@+id/textview_drawable_2_1"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:drawableStart="@drawable/icon_blue"
+ android:drawableEnd="@drawable/icon_red"
+ android:drawableTop="@drawable/icon_green"
+ android:drawableBottom="@drawable/icon_yellow"
+ android:layoutDirection="ltr" />
+
+ <TextView
+ android:id="@+id/textview_drawable_2_2"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:drawableStart="@drawable/icon_blue"
+ android:drawableEnd="@drawable/icon_red"
+ android:drawableTop="@drawable/icon_green"
+ android:drawableBottom="@drawable/icon_yellow"
+ android:layoutDirection="rtl" />
+
+ <TextView
+ android:id="@+id/textview_drawable_3_1"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:drawableLeft="@drawable/icon_black"
+ android:drawableRight="@drawable/icon_black"
+ android:drawableStart="@drawable/icon_blue"
+ android:drawableEnd="@drawable/icon_red"
+ android:drawableTop="@drawable/icon_green"
+ android:drawableBottom="@drawable/icon_yellow"
+ android:layoutDirection="ltr" />
+
+ <TextView
+ android:id="@+id/textview_drawable_3_2"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:drawableLeft="@drawable/icon_black"
+ android:drawableRight="@drawable/icon_black"
+ android:drawableStart="@drawable/icon_blue"
+ android:drawableEnd="@drawable/icon_red"
+ android:drawableTop="@drawable/icon_green"
+ android:drawableBottom="@drawable/icon_yellow"
+ android:layoutDirection="rtl" />
+
+ <LinearLayout
+ android:orientation="vertical"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="wrap_content"
+ android:layoutDirection="ltr">
- <TextView android:id="@+id/textview_textAttr"
- android:fontFamily="@null"
- android:text="@string/text_view_hello"
- android:textColor="@drawable/black"
- android:textColorHighlight="@drawable/yellow"
- android:textColorHint="@drawable/red"
- android:textColorLink="@drawable/blue"
- android:textScaleX="1.2"
- android:typeface="normal"
- android:textSize="20px"
- android:textStyle="normal"
- android:textAppearance="@null"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-
- <TextView android:id="@+id/textview_password"
- android:password="true"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-
- <TextView android:id="@+id/textview_singleLine"
- android:singleLine="true"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-
- <TextView android:id="@+id/textview_text"
- android:text="@string/text_view_hello"
- android:breakStrategy="simple"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-
- <TextView android:id="@+id/textview_text_two_lines"
- android:text="@string/text_view_hello_two_lines"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-
- <android.widget.cts.MockTextView
- android:id="@+id/mock_textview_left"
- android:layout_width="wrap_content"
+ <TextView
+ android:id="@+id/textview_drawable_4_1"
android:layout_height="wrap_content"
- android:requiresFadingEdge="horizontal"
- android:singleLine="true"
- android:text="@string/long_text"
- android:gravity="left"
- />
-
- <android.widget.cts.MockTextView
- android:id="@+id/mock_textview_right"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:requiresFadingEdge="horizontal"
- android:singleLine="true"
- android:text="@string/long_text"
- android:gravity="right"
- />
+ android:drawableStart="@drawable/icon_blue"
+ android:drawableEnd="@drawable/icon_red"
+ android:drawableTop="@drawable/icon_green"
+ android:drawableBottom="@drawable/icon_yellow" />
- <android.widget.cts.MockTextView
- android:id="@+id/mock_textview_center"
- android:layout_width="wrap_content"
+ <TextView
+ android:id="@+id/textview_drawable_5_1"
android:layout_height="wrap_content"
- android:requiresFadingEdge="horizontal"
- android:singleLine="true"
- android:text="@string/long_text"
- android:gravity="center"
- />
+ android:layout_width="wrap_content"
+ android:drawableLeft="@drawable/icon_black"
+ android:drawableRight="@drawable/icon_black"
+ android:drawableStart="@drawable/icon_blue"
+ android:drawableEnd="@drawable/icon_red"
+ android:drawableTop="@drawable/icon_green"
+ android:drawableBottom="@drawable/icon_yellow" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layoutDirection="rtl">
+
+ <TextView
+ android:id="@+id/textview_drawable_4_2"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:drawableStart="@drawable/icon_blue"
+ android:drawableEnd="@drawable/icon_red"
+ android:drawableTop="@drawable/icon_green"
+ android:drawableBottom="@drawable/icon_yellow" />
+
+ <TextView
+ android:id="@+id/textview_drawable_5_2"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:drawableLeft="@drawable/icon_black"
+ android:drawableRight="@drawable/icon_black"
+ android:drawableStart="@drawable/icon_blue"
+ android:drawableEnd="@drawable/icon_red"
+ android:drawableTop="@drawable/icon_green"
+ android:drawableBottom="@drawable/icon_yellow" />
+
+ </LinearLayout>
+
+
+ <TextView
+ android:id="@+id/textview_compound_drawable_ltr"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:paddingLeft="@dimen/textview_padding_left"
+ android:paddingRight="@dimen/textview_padding_right"
+ android:paddingTop="@dimen/textview_padding_top"
+ android:paddingBottom="@dimen/textview_padding_bottom"
+ android:drawablePadding="@dimen/textview_drawable_padding"
+ android:drawableStart="@drawable/icon_blue"
+ android:drawableEnd="@drawable/icon_red"
+ android:drawableTop="@drawable/icon_green"
+ android:drawableBottom="@drawable/icon_yellow"
+ android:layoutDirection="ltr" />
+
+ <TextView
+ android:id="@+id/textview_compound_drawable_rtl"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:paddingLeft="@dimen/textview_padding_left"
+ android:paddingRight="@dimen/textview_padding_right"
+ android:paddingTop="@dimen/textview_padding_top"
+ android:paddingBottom="@dimen/textview_padding_bottom"
+ android:drawablePadding="@dimen/textview_drawable_padding"
+ android:drawableStart="@drawable/icon_blue"
+ android:drawableEnd="@drawable/icon_red"
+ android:drawableTop="@drawable/icon_green"
+ android:drawableBottom="@drawable/icon_yellow"
+ android:layoutDirection="rtl" />
+
+ <TextView
+ android:id="@+id/textview_with_shadow"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/text_view_hello"
+ android:shadowDx="1.0"
+ android:shadowDy="2.0"
+ android:shadowRadius="3.0"
+ android:shadowColor="@color/testcolor1" />
+
+ <EditText
+ android:id="@+id/editview_text"
+ android:text="@string/text_view_hello"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
</LinearLayout>
- </ScrollView>
-
- <TextView android:id="@+id/textview_ltr"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"/>
-
- <TextView android:id="@+id/textview_rtl"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"/>
-
- <TextView android:id="@+id/textview_drawable_1_1"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:drawableLeft="@drawable/icon_blue"
- android:drawableRight="@drawable/icon_red"
- android:drawableTop="@drawable/icon_green"
- android:drawableBottom="@drawable/icon_yellow"
- />
-
- <TextView android:id="@+id/textview_drawable_1_2"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:drawableLeft="@drawable/icon_blue"
- android:drawableRight="@drawable/icon_red"
- android:drawableTop="@drawable/icon_green"
- android:drawableBottom="@drawable/icon_yellow"
- android:layoutDirection="rtl"
- />
-
- <TextView android:id="@+id/textview_drawable_2_1"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:drawableStart="@drawable/icon_blue"
- android:drawableEnd="@drawable/icon_red"
- android:drawableTop="@drawable/icon_green"
- android:drawableBottom="@drawable/icon_yellow"
- />
-
- <TextView android:id="@+id/textview_drawable_2_2"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:drawableStart="@drawable/icon_blue"
- android:drawableEnd="@drawable/icon_red"
- android:drawableTop="@drawable/icon_green"
- android:drawableBottom="@drawable/icon_yellow"
- android:layoutDirection="rtl"
- />
-
- <TextView android:id="@+id/textview_drawable_3_1"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:drawableLeft="@drawable/icon_black"
- android:drawableRight="@drawable/icon_black"
- android:drawableStart="@drawable/icon_blue"
- android:drawableEnd="@drawable/icon_red"
- android:drawableTop="@drawable/icon_green"
- android:drawableBottom="@drawable/icon_yellow"
- />
-
- <TextView android:id="@+id/textview_drawable_3_2"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:drawableLeft="@drawable/icon_black"
- android:drawableRight="@drawable/icon_black"
- android:drawableStart="@drawable/icon_blue"
- android:drawableEnd="@drawable/icon_red"
- android:drawableTop="@drawable/icon_green"
- android:drawableBottom="@drawable/icon_yellow"
- android:layoutDirection="rtl"
- />
-
-
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layoutDirection="ltr">
-
- <TextView android:id="@+id/textview_drawable_4_1"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:drawableStart="@drawable/icon_blue"
- android:drawableEnd="@drawable/icon_red"
- android:drawableTop="@drawable/icon_green"
- android:drawableBottom="@drawable/icon_yellow"
- />
-
- <TextView android:id="@+id/textview_drawable_5_1"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:drawableLeft="@drawable/icon_black"
- android:drawableRight="@drawable/icon_black"
- android:drawableStart="@drawable/icon_blue"
- android:drawableEnd="@drawable/icon_red"
- android:drawableTop="@drawable/icon_green"
- android:drawableBottom="@drawable/icon_yellow"
- />
-
- </LinearLayout>
-
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layoutDirection="rtl">
-
- <TextView android:id="@+id/textview_drawable_4_2"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:drawableStart="@drawable/icon_blue"
- android:drawableEnd="@drawable/icon_red"
- android:drawableTop="@drawable/icon_green"
- android:drawableBottom="@drawable/icon_yellow"
- />
-
- <TextView android:id="@+id/textview_drawable_5_2"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:drawableLeft="@drawable/icon_black"
- android:drawableRight="@drawable/icon_black"
- android:drawableStart="@drawable/icon_blue"
- android:drawableEnd="@drawable/icon_red"
- android:drawableTop="@drawable/icon_green"
- android:drawableBottom="@drawable/icon_yellow"
- />
-
- </LinearLayout>
-
-</LinearLayout>
+</ScrollView>
diff --git a/tests/tests/widget/res/layout/timepicker.xml b/tests/tests/widget/res/layout/timepicker.xml
index 352f69b..a8273b2 100644
--- a/tests/tests/widget/res/layout/timepicker.xml
+++ b/tests/tests/widget/res/layout/timepicker.xml
@@ -14,6 +14,8 @@
limitations under the License.
-->
-<TimePicker xmlns:android="http://schemas.android.com/apk/res/android"
+<TimePicker
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/timepicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
diff --git a/tests/tests/widget/res/layout/togglebutton_layout.xml b/tests/tests/widget/res/layout/togglebutton_layout.xml
index a6c08e1..de2faf3 100644
--- a/tests/tests/widget/res/layout/togglebutton_layout.xml
+++ b/tests/tests/widget/res/layout/togglebutton_layout.xml
@@ -15,8 +15,8 @@
* limitations under the License.
-->
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
@@ -25,19 +25,35 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
- <ToggleButton android:id="@+id/toggle1"
+ <ToggleButton
+ android:id="@+id/toggle1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
- <ToggleButton android:id="@+id/toggle2"
+ <ToggleButton
+ android:id="@+id/toggle2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
- <ToggleButton android:id="@+id/button_tint"
+ <ToggleButton
+ android:id="@+id/toggle_with_defaults"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textOn="@string/toggle_text_on_alt"
+ android:textOff="@string/toggle_text_off_alt" />
+
+ <ToggleButton
+ style="@style/Theme_Toggle"
+ android:id="@+id/toggle_with_style"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <ToggleButton
+ android:id="@+id/button_tint"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:buttonTint="@android:color/white"
- android:buttonTintMode="src_over"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
+ android:buttonTintMode="src_over" />
</LinearLayout>
diff --git a/tests/tests/widget/res/layout/zoombutton_layout.xml b/tests/tests/widget/res/layout/zoombutton_layout.xml
index 1b1e0b2..49031a8 100644
--- a/tests/tests/widget/res/layout/zoombutton_layout.xml
+++ b/tests/tests/widget/res/layout/zoombutton_layout.xml
@@ -14,9 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
-<ZoomButton xmlns:android="http://schemas.android.com/apk/res/android"
+<ZoomButton
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/zoombutton_test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
-/>
+ android:src="@drawable/icon_red" />
diff --git a/tests/tests/widget/res/values/attrs.xml b/tests/tests/widget/res/values/attrs.xml
index 4c3d9db..b2bea6f 100644
--- a/tests/tests/widget/res/values/attrs.xml
+++ b/tests/tests/widget/res/values/attrs.xml
@@ -142,4 +142,7 @@
<attr name="themeGravity" />
<attr name="themeTileMode" />
<attr name="themeAngle" />
+
+ <attr name="chronometerStyle" format="string" />
+
</resources>
diff --git a/tests/tests/widget/res/values/dimens.xml b/tests/tests/widget/res/values/dimens.xml
index 3690039..7cbff3a 100644
--- a/tests/tests/widget/res/values/dimens.xml
+++ b/tests/tests/widget/res/values/dimens.xml
@@ -15,4 +15,33 @@
-->
<resources>
<dimen name="popup_row_height">48dp</dimen>
+
+ <dimen name="switch_padding">24dp</dimen>
+ <dimen name="switch_thumb_text_padding">12dp</dimen>
+ <dimen name="switch_min_width">160dp</dimen>
+ <dimen name="switch_min_width2">200dp</dimen>
+
+ <dimen name="autocomplete_textview_dropdown_height">120dp</dimen>
+ <dimen name="autocomplete_textview_dropdown_width">160dp</dimen>
+ <dimen name="autocomplete_textview_dropdown_offset_h">24dp</dimen>
+ <dimen name="autocomplete_textview_dropdown_offset_v">32dp</dimen>
+
+ <dimen name="spinner_dropdown_width">200dp</dimen>
+ <dimen name="spinner_dropdown_offset_h">64dp</dimen>
+ <dimen name="spinner_dropdown_offset_v">48dp</dimen>
+
+ <dimen name="search_view_max_width">160dp</dimen>
+ <dimen name="search_view_max_width2">200dp</dimen>
+ <dimen name="search_view_suggestion_row_height">48dp</dimen>
+
+ <dimen name="linear_layout_divider_size">10px</dimen>
+ <dimen name="linear_layout_divider_padding">8px</dimen>
+
+ <dimen name="textview_padding_left">4dip</dimen>
+ <dimen name="textview_padding_right">6dip</dimen>
+ <dimen name="textview_padding_start">8dip</dimen>
+ <dimen name="textview_padding_end">10dip</dimen>
+ <dimen name="textview_padding_top">2dip</dimen>
+ <dimen name="textview_padding_bottom">4dip</dimen>
+ <dimen name="textview_drawable_padding">2dip</dimen>
</resources>
\ No newline at end of file
diff --git a/tests/tests/widget/res/values/strings.xml b/tests/tests/widget/res/values/strings.xml
index 63ceffa..3820072 100644
--- a/tests/tests/widget/res/values/strings.xml
+++ b/tests/tests/widget/res/values/strings.xml
@@ -193,4 +193,15 @@
<string name="toolbar_subtitle">Toolbar subtitle</string>
<string name="toolbar_navigation">Toolbar navigation</string>
<string name="toolbar_logo">Toolbar logo</string>
+
+ <string name="search_query_hint">query hint</string>
+
+ <string name="remote_content_description">remote description</string>
+
+ <string name="toggle_text_on">On</string>
+ <string name="toggle_text_off">Off</string>
+ <string name="toggle_text_on_alt">On Alt</string>
+ <string name="toggle_text_off_alt">Off Alt</string>
+
+ <string name="chronometer_format">Current count: %s</string>
</resources>
diff --git a/tests/tests/widget/res/values/styles.xml b/tests/tests/widget/res/values/styles.xml
index 345b450..bddc891 100644
--- a/tests/tests/widget/res/values/styles.xml
+++ b/tests/tests/widget/res/values/styles.xml
@@ -202,4 +202,19 @@
</style>
<style name="ToolbarPopupTheme_Test" parent="@android:style/ThemeOverlay.Material.Light" />
+
+ <style name="Theme_Toggle" parent="@android:style/Widget.Material.Light.Button.Toggle">
+ <item name="android:textOn">@string/toggle_text_on</item>
+ <item name="android:textOff">@string/toggle_text_off</item>
+ </style>
+
+ <style name="ChronometerStyle" parent="@android:style/Widget.Material.Light.TextView">
+ <item name="android:format">@string/chronometer_format</item>
+ <item name="android:countDown">true</item>
+ </style>
+
+ <style name="ChronometerAwareTheme" parent="@android:style/Theme.Material.Light">
+ <item name="chronometerStyle">@style/ChronometerStyle</item>
+ </style>
+
</resources>
diff --git a/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java b/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
index cf8012e..d080e0a 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
@@ -16,12 +16,6 @@
package android.widget.cts;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.widget.cts.R;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
@@ -33,6 +27,7 @@
import android.graphics.drawable.Drawable;
import android.test.ActivityInstrumentationTestCase2;
import android.test.TouchUtils;
+import android.test.suitebuilder.annotation.MediumTest;
import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.util.AttributeSet;
@@ -42,17 +37,29 @@
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
-import android.widget.AbsListView.RecyclerListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
+import android.widget.cts.util.TestUtilsMatchers;
+
+import org.hamcrest.MatcherAssert;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.mockito.Mockito.*;
public class AbsListViewTest extends ActivityInstrumentationTestCase2<ListViewCtsActivity> {
private final String[] mShortList = new String[] {
@@ -83,12 +90,7 @@
super.setUp();
mActivity = getActivity();
- new PollingCheck() {
- @Override
- protected boolean check() {
- return mActivity.hasWindowFocus();
- }
- }.run();
+ PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
mInstrumentation = getInstrumentation();
XmlPullParser parser = mActivity.getResources().getXml(R.layout.listview_layout);
@@ -156,90 +158,110 @@
});
mInstrumentation.waitForIdleSync();
}
+
public void testSetOnScrollListener() throws Throwable {
- MockOnScrollListener onScrollListener = new MockOnScrollListener();
+ AbsListView.OnScrollListener mockScrollListener =
+ mock(AbsListView.OnScrollListener.class);
- assertNull(onScrollListener.getView());
- assertEquals(0, onScrollListener.getFirstVisibleItem());
- assertEquals(0, onScrollListener.getVisibleItemCount());
- assertEquals(0, onScrollListener.getTotalItemCount());
- assertEquals(-1, onScrollListener.getScrollState());
+ verifyZeroInteractions(mockScrollListener);
- assertFalse(onScrollListener.isOnScrollCalled());
- assertFalse(onScrollListener.isOnScrollStateChangedCalled());
+ mListView.setOnScrollListener(mockScrollListener);
+ verify(mockScrollListener, times(1)).onScroll(mListView, 0, 0, 0);
+ verifyNoMoreInteractions(mockScrollListener);
- mListView.setOnScrollListener(onScrollListener);
- assertSame(mListView, onScrollListener.getView());
- assertEquals(0, onScrollListener.getFirstVisibleItem());
- assertEquals(0, onScrollListener.getVisibleItemCount());
- assertEquals(0, onScrollListener.getTotalItemCount());
- assertEquals(-1, onScrollListener.getScrollState());
-
- assertTrue(onScrollListener.isOnScrollCalled());
- assertFalse(onScrollListener.isOnScrollStateChangedCalled());
- onScrollListener.reset();
+ reset(mockScrollListener);
setAdapter();
+ verify(mockScrollListener, times(1)).onScroll(mListView, 0, mListView.getChildCount(),
+ mCountryList.length);
+ verifyNoMoreInteractions(mockScrollListener);
- assertSame(mListView, onScrollListener.getView());
- assertEquals(0, onScrollListener.getFirstVisibleItem());
- assertEquals(mListView.getChildCount(), onScrollListener.getVisibleItemCount());
- assertEquals(mCountryList.length, onScrollListener.getTotalItemCount());
- assertEquals(-1, onScrollListener.getScrollState());
-
- assertTrue(onScrollListener.isOnScrollCalled());
- assertFalse(onScrollListener.isOnScrollStateChangedCalled());
- onScrollListener.reset();
+ reset(mockScrollListener);
TouchUtils.scrollToBottom(this, mActivity, mListView);
- assertSame(mListView, onScrollListener.getView());
- assertEquals(mListView.getChildCount(), onScrollListener.getVisibleItemCount());
- assertEquals(mCountryList.length, onScrollListener.getTotalItemCount());
- assertTrue(onScrollListener.isOnScrollCalled());
- assertTrue(onScrollListener.isOnScrollStateChangedCalled());
+ ArgumentCaptor<Integer> firstVisibleItemCaptor = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> visibleItemCountCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mockScrollListener, atLeastOnce()).onScroll(eq(mListView),
+ firstVisibleItemCaptor.capture(), visibleItemCountCaptor.capture(),
+ eq(mCountryList.length));
+
+ // We expect the first visible item values to be increasing
+ MatcherAssert.assertThat(firstVisibleItemCaptor.getAllValues(),
+ TestUtilsMatchers.inAscendingOrder());
+ // The number of visible items during scrolling may change depending on the specific
+ // scroll position. As such we only test this number at the very end
+ final List<Integer> capturedVisibleItemCounts = visibleItemCountCaptor.getAllValues();
+ assertEquals(mListView.getChildCount(),
+ (int) capturedVisibleItemCounts.get(capturedVisibleItemCounts.size() - 1));
+
+ ArgumentCaptor<Integer> scrollStateCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mockScrollListener, atLeastOnce()).onScrollStateChanged(eq(mListView),
+ scrollStateCaptor.capture());
+
+ // Verify that the last scroll state is IDLE
+ final List<Integer> capturedScrollStates = scrollStateCaptor.getAllValues();
+ assertEquals(AbsListView.OnScrollListener.SCROLL_STATE_IDLE,
+ (int) capturedScrollStates.get(capturedScrollStates.size() - 1));
}
public void testFling() throws Throwable {
- MockOnScrollListener onScrollListener = new MockOnScrollListener();
- mListView.setOnScrollListener(onScrollListener);
+ AbsListView.OnScrollListener mockScrollListener = mock(AbsListView.OnScrollListener.class);
+ mListView.setOnScrollListener(mockScrollListener);
setAdapter();
// Fling down from top, expect a scroll.
- fling(10000, onScrollListener);
- assertTrue(onScrollListener.isOnScrollCalled());
- assertTrue(0 < onScrollListener.getFirstVisibleItem());
+ fling(10000, mockScrollListener);
+ ArgumentCaptor<Integer> firstVisibleItemCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mockScrollListener, atLeastOnce()).onScroll(eq(mListView),
+ firstVisibleItemCaptor.capture(), anyInt(), eq(mCountryList.length));
+ List<Integer> capturedFirstVisibleItems = firstVisibleItemCaptor.getAllValues();
+ assertTrue(capturedFirstVisibleItems.get(capturedFirstVisibleItems.size() - 1) > 0);
// Fling up the same amount, expect a scroll to the original position.
- fling(-10000, onScrollListener);
- assertTrue(onScrollListener.isOnScrollCalled());
- assertEquals(0, onScrollListener.getFirstVisibleItem());
+ fling(-10000, mockScrollListener);
+ firstVisibleItemCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mockScrollListener, atLeastOnce()).onScroll(eq(mListView),
+ firstVisibleItemCaptor.capture(), anyInt(), eq(mCountryList.length));
+ capturedFirstVisibleItems = firstVisibleItemCaptor.getAllValues();
+ assertTrue(capturedFirstVisibleItems.get(capturedFirstVisibleItems.size() - 1) == 0);
// Fling up again, expect no scroll, as the viewport is already at top.
- fling(-10000, onScrollListener);
- assertFalse(onScrollListener.isOnScrollCalled());
- assertEquals(0, onScrollListener.getFirstVisibleItem());
+ fling(-10000, mockScrollListener);
+ verify(mockScrollListener, never()).onScroll(any(AbsListView.class), anyInt(), anyInt(),
+ anyInt());
// Fling up again with a huge velocity, expect no scroll.
- fling(-50000, onScrollListener);
- assertFalse(onScrollListener.isOnScrollCalled());
- assertEquals(0, onScrollListener.getFirstVisibleItem());
+ fling(-50000, mockScrollListener);
+ verify(mockScrollListener, never()).onScroll(any(AbsListView.class), anyInt(), anyInt(),
+ anyInt());
}
- private void fling(int velocityY, MockOnScrollListener onScrollListener) throws Throwable {
- onScrollListener.reset();
+ private void fling(int velocityY, OnScrollListener mockScrollListener) throws Throwable {
+ reset(mockScrollListener);
- final int v = velocityY;
- runTestOnUiThread(new Runnable() {
- public void run() {
- mListView.fling(v);
- }
- });
+ // Create a count down latch and configure it to be counted down when out mock
+ // listener is invoked with IDLE state
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) {
+ countDownLatch.countDown();
+ return null;
+ }
+ }
+ ).when(mockScrollListener).onScrollStateChanged(
+ mListView, OnScrollListener.SCROLL_STATE_IDLE);
- do {
- mInstrumentation.waitForIdleSync();
- } while (onScrollListener.getScrollState() != OnScrollListener.SCROLL_STATE_IDLE);
+ // Now fling the list view
+ runTestOnUiThread(() -> mListView.fling(velocityY));
+
+ // And wait for the latch to be triggered
+ try {
+ assertTrue(countDownLatch.await(20L, TimeUnit.SECONDS));
+ } catch (InterruptedException e) {
+ }
}
public void testGetFocusedRect() throws Throwable {
@@ -358,12 +380,7 @@
final Rect r = drawable.getBounds();
final TextView v = (TextView) mListView.getSelectedView();
- new PollingCheck() {
- @Override
- protected boolean check() {
- return v.getRight() == r.right;
- }
- }.run();
+ PollingCheck.waitFor(() -> v.getRight() == r.right);
assertEquals(v.getLeft(), r.left);
assertEquals(v.getTop(), r.top);
assertEquals(v.getBottom(), r.bottom);
@@ -428,17 +445,23 @@
public void testSetRecyclerListener() throws Throwable {
setAdapter();
- MockRecyclerListener recyclerListener = new MockRecyclerListener();
- List<View> views = new ArrayList<View>();
+ AbsListView.RecyclerListener mockRecyclerListener =
+ mock(AbsListView.RecyclerListener.class);
+ verifyZeroInteractions(mockRecyclerListener);
- assertNull(recyclerListener.getView());
- mListView.setRecyclerListener(recyclerListener);
+ mListView.setRecyclerListener(mockRecyclerListener);
+ List<View> views = new ArrayList<>();
mListView.reclaimViews(views);
assertTrue(views.size() > 0);
- assertNotNull(recyclerListener.getView());
- assertSame(recyclerListener.getView(), views.get(views.size() - 1));
+ // Verify that onMovedToScrapHeap was called on each view in the order that they were
+ // put in the list that we passed to reclaimViews
+ final InOrder reclaimedOrder = inOrder(mockRecyclerListener);
+ for (View reclaimed : views) {
+ reclaimedOrder.verify(mockRecyclerListener, times(1)).onMovedToScrapHeap(reclaimed);
+ }
+ verifyNoMoreInteractions(mockRecyclerListener);
}
public void testAccessCacheColorHint() {
@@ -577,27 +600,37 @@
final TextView v = (TextView) listView.getSelectedView();
assertNull(listView.getContextMenuInfo());
- final MockOnItemLongClickListener listener = new MockOnItemLongClickListener();
- listView.setOnItemLongClickListener(listener);
+ final AbsListView.OnItemLongClickListener mockOnItemLongClickListener =
+ mock(AbsListView.OnItemLongClickListener.class);
+ listView.setOnItemLongClickListener(mockOnItemLongClickListener);
- assertNull(listener.getParent());
- assertNull(listener.getView());
- assertEquals(0, listener.getPosition());
- assertEquals(0, listener.getID());
+ verifyZeroInteractions(mockOnItemLongClickListener);
+
+ // Create a count down latch and configure it to be counted down when out mock
+ // listener is invoked with the expected view
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) {
+ countDownLatch.countDown();
+ return null;
+ }
+ }).when(mockOnItemLongClickListener).onItemLongClick(listView, v, 2,
+ listView.getItemIdAtPosition(2));
mInstrumentation.waitForIdleSync();
+
+ // Now long click our view
TouchUtils.longClickView(this, v);
- new PollingCheck() {
- @Override
- protected boolean check() {
- return v == listener.getView();
- }
- }.run();
+ // And wait for the latch to be triggered
+ try {
+ assertTrue(countDownLatch.await(20L, TimeUnit.SECONDS));
+ } catch (InterruptedException e) {
+ }
- assertSame(listView, listener.getParent());
- assertEquals(2, listener.getPosition());
- assertEquals(listView.getItemIdAtPosition(2), listener.getID());
+ verify(mockOnItemLongClickListener, times(1)).onItemLongClick(listView, v, 2,
+ listView.getItemIdAtPosition(2));
ContextMenuInfo cmi = listView.getContextMenuInfo();
assertNotNull(cmi);
@@ -748,131 +781,6 @@
*/
}
- public void testFoo() {
- /**
- * Do not test these APIs. They are callbacks which:
- *
- * 1. The callback machanism has been tested in super class
- * 2. The functionality is implmentation details, no need to test
- */
- }
-
- private static class MockOnScrollListener implements OnScrollListener {
- private AbsListView mView;
- private int mFirstVisibleItem;
- private int mVisibleItemCount;
- private int mTotalItemCount;
- private int mScrollState;
-
- private boolean mIsOnScrollCalled;
- private boolean mIsOnScrollStateChangedCalled;
-
- private MockOnScrollListener() {
- mView = null;
- mFirstVisibleItem = 0;
- mVisibleItemCount = 0;
- mTotalItemCount = 0;
- mScrollState = -1;
-
- mIsOnScrollCalled = false;
- mIsOnScrollStateChangedCalled = false;
- }
-
- public void onScroll(AbsListView view, int firstVisibleItem,
- int visibleItemCount, int totalItemCount) {
- mView = view;
- mFirstVisibleItem = firstVisibleItem;
- mVisibleItemCount = visibleItemCount;
- mTotalItemCount = totalItemCount;
- mIsOnScrollCalled = true;
- }
-
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- mScrollState = scrollState;
- mIsOnScrollStateChangedCalled = true;
- }
-
- public AbsListView getView() {
- return mView;
- }
-
- public int getFirstVisibleItem() {
- return mFirstVisibleItem;
- }
-
- public int getVisibleItemCount() {
- return mVisibleItemCount;
- }
-
- public int getTotalItemCount() {
- return mTotalItemCount;
- }
-
- public int getScrollState() {
- return mScrollState;
- }
-
- public boolean isOnScrollCalled() {
- return mIsOnScrollCalled;
- }
-
- public boolean isOnScrollStateChangedCalled() {
- return mIsOnScrollStateChangedCalled;
- }
-
- public void reset() {
- mIsOnScrollCalled = false;
- mIsOnScrollStateChangedCalled = false;
- }
- }
-
- private static class MockRecyclerListener implements RecyclerListener {
- private View mView;
-
- private MockRecyclerListener() {
- mView = null;
- }
-
- public void onMovedToScrapHeap(View view) {
- mView = view;
- }
-
- public View getView() {
- return mView;
- }
- }
-
- private static class MockOnItemLongClickListener implements OnItemLongClickListener {
- private AdapterView<?> parent;
- private View view;
- private int position;
- private long id;
-
- public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
- this.parent = parent;
- this.view = view;
- this.position = position;
- this.id = id;
- return false;
- }
-
- public AdapterView<?> getParent() {
- return parent;
- }
-
- public View getView() {
- return view;
- }
-
- public int getPosition() {
- return position;
- }
-
- public long getID() {
- return id;
- }
- }
-
/**
* MyListView for test
*/
diff --git a/tests/tests/widget/src/android/widget/cts/AbsSeekBarCtsActivity.java b/tests/tests/widget/src/android/widget/cts/AbsSeekBarCtsActivity.java
new file mode 100644
index 0000000..1bac1f5
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/AbsSeekBarCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.AbsSeekBar;
+
+/**
+ * A minimal application for {@link AbsSeekBar} test
+ */
+public class AbsSeekBarCtsActivity extends Activity {
+ /**
+ * Called when the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.seekbar_layout);
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java b/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java
index 93032f6..e2108d9 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java
@@ -16,16 +16,14 @@
package android.widget.cts;
-import android.widget.cts.R;
-
import android.app.Activity;
+import android.app.Instrumentation;
import android.content.Context;
import android.content.res.ColorStateList;
import android.cts.util.PollingCheck;
-import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.ColorFilter;
import android.graphics.PorterDuff;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
@@ -33,21 +31,31 @@
import android.view.KeyEvent;
import android.widget.AbsSeekBar;
import android.widget.SeekBar;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
+
+import org.mockito.ArgumentCaptor;
+
+import java.util.List;
+
+import static org.mockito.Mockito.*;
/**
* Test {@link AbsSeekBar}.
*/
-public class AbsSeekBarTest extends ActivityInstrumentationTestCase2<ProgressBarCtsActivity> {
+public class AbsSeekBarTest extends ActivityInstrumentationTestCase2<AbsSeekBarCtsActivity> {
public AbsSeekBarTest() {
- super("android.widget.cts", ProgressBarCtsActivity.class);
+ super("android.widget.cts", AbsSeekBarCtsActivity.class);
}
+ private Instrumentation mInstrumentation;
private Activity mActivity;
@Override
protected void setUp() throws Exception {
super.setUp();
+ mInstrumentation = getInstrumentation();
mActivity = getActivity();
}
@@ -57,6 +65,8 @@
new MyAbsSeekBar(mActivity, null);
new MyAbsSeekBar(mActivity, null, android.R.attr.progressBarStyle);
+
+ new MyAbsSeekBar(mActivity, null, 0, android.R.style.Widget_Material_Light_ProgressBar);
}
public void testAccessThumbOffset() {
@@ -75,56 +85,74 @@
assertEquals(negative, myAbsSeekBar.getThumbOffset());
}
- public void testSetThumb() {
- MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity);
+ public void testAccessThumb() {
+ // Both are pointing to the same object. This works around current limitation in CTS
+ // coverage report tool for properly reporting coverage of base class method calls.
+ final MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity);
+ final AbsSeekBar absSeekBar = myAbsSeekBar;
+
Drawable drawable1 = mActivity.getDrawable(R.drawable.scenery);
Drawable drawable2 = mActivity.getDrawable(R.drawable.pass);
assertFalse(myAbsSeekBar.verifyDrawable(drawable1));
assertFalse(myAbsSeekBar.verifyDrawable(drawable2));
- myAbsSeekBar.setThumb(drawable1);
- assertSame(drawable1, myAbsSeekBar.getThumb());
+ absSeekBar.setThumb(drawable1);
+ assertSame(drawable1, absSeekBar.getThumb());
assertTrue(myAbsSeekBar.verifyDrawable(drawable1));
assertFalse(myAbsSeekBar.verifyDrawable(drawable2));
- myAbsSeekBar.setThumb(drawable2);
- assertSame(drawable2, myAbsSeekBar.getThumb());
+ absSeekBar.setThumb(drawable2);
+ assertSame(drawable2, absSeekBar.getThumb());
assertFalse(myAbsSeekBar.verifyDrawable(drawable1));
assertTrue(myAbsSeekBar.verifyDrawable(drawable2));
}
- public void testSetTickMark() {
- MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity);
+ public void testAccessTickMark() {
+ // Both are pointing to the same object. This works around current limitation in CTS
+ // coverage report tool for properly reporting coverage of base class method calls.
+ final MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity);
+ final AbsSeekBar absSeekBar = myAbsSeekBar;
+
Drawable drawable1 = mActivity.getDrawable(R.drawable.black);
Drawable drawable2 = mActivity.getDrawable(R.drawable.black);
assertFalse(myAbsSeekBar.verifyDrawable(drawable1));
assertFalse(myAbsSeekBar.verifyDrawable(drawable2));
- myAbsSeekBar.setTickMark(drawable1);
- assertSame(drawable1, myAbsSeekBar.getTickMark());
+ absSeekBar.setTickMark(drawable1);
+ assertSame(drawable1, absSeekBar.getTickMark());
assertTrue(myAbsSeekBar.verifyDrawable(drawable1));
assertFalse(myAbsSeekBar.verifyDrawable(drawable2));
- myAbsSeekBar.setTickMark(drawable2);
- assertSame(drawable2, myAbsSeekBar.getTickMark());
+ absSeekBar.setTickMark(drawable2);
+ assertSame(drawable2, absSeekBar.getTickMark());
assertFalse(myAbsSeekBar.verifyDrawable(drawable1));
assertTrue(myAbsSeekBar.verifyDrawable(drawable2));
}
public void testDrawableStateChanged() {
MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity);
- MockDrawable drawable = new MockDrawable();
- myAbsSeekBar.setProgressDrawable(drawable);
+ Drawable mockProgressDrawable = spy(new ColorDrawable(Color.YELLOW));
+ myAbsSeekBar.setProgressDrawable(mockProgressDrawable);
+ ArgumentCaptor<Integer> alphaCaptor = ArgumentCaptor.forClass(Integer.class);
myAbsSeekBar.setEnabled(false);
myAbsSeekBar.drawableStateChanged();
- assertEquals(0, drawable.getAlpha());
+ verify(mockProgressDrawable, atLeastOnce()).setAlpha(alphaCaptor.capture());
+ // Verify that the last call to setAlpha was with argument 0x00
+ List<Integer> alphaCaptures = alphaCaptor.getAllValues();
+ assertTrue(!alphaCaptures.isEmpty());
+ assertEquals(Integer.valueOf(0x00), alphaCaptures.get(alphaCaptures.size() - 1));
+ alphaCaptor = ArgumentCaptor.forClass(Integer.class);
myAbsSeekBar.setEnabled(true);
myAbsSeekBar.drawableStateChanged();
- assertEquals(0xFF, drawable.getAlpha());
+ verify(mockProgressDrawable, atLeastOnce()).setAlpha(alphaCaptor.capture());
+ // Verify that the last call to setAlpha was with argument 0xFF
+ alphaCaptures = alphaCaptor.getAllValues();
+ assertTrue(!alphaCaptures.isEmpty());
+ assertEquals(Integer.valueOf(0xFF), alphaCaptures.get(alphaCaptures.size() - 1));
}
public void testVerifyDrawable() {
@@ -162,42 +190,31 @@
public void testAccessKeyProgressIncrement() throws Throwable {
// AbsSeekBar is an abstract class, use its subclass: SeekBar to do this test.
- runTestOnUiThread(new Runnable() {
- public void run() {
- mActivity.setContentView(R.layout.seekbar_layout);
- }
- });
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> mActivity.setContentView(R.layout.seekbar_layout));
+ mInstrumentation.waitForIdleSync();
final SeekBar seekBar = (SeekBar) mActivity.findViewById(R.id.seekBar);
final int keyProgressIncrement = 2;
- runTestOnUiThread(new Runnable() {
- public void run() {
- seekBar.setKeyProgressIncrement(keyProgressIncrement);
- seekBar.setFocusable(true);
- seekBar.requestFocus();
- }
+ mInstrumentation.runOnMainSync(() -> {
+ seekBar.setKeyProgressIncrement(keyProgressIncrement);
+ seekBar.setFocusable(true);
+ seekBar.requestFocus();
});
- new PollingCheck(1000) {
- @Override
- protected boolean check() {
- return seekBar.hasWindowFocus();
- }
- }.run();
+ PollingCheck.waitFor(1000, () -> seekBar.hasWindowFocus());
assertEquals(keyProgressIncrement, seekBar.getKeyProgressIncrement());
int oldProgress = seekBar.getProgress();
KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT);
- getInstrumentation().sendKeySync(keyEvent);
+ mInstrumentation.sendKeySync(keyEvent);
assertEquals(oldProgress + keyProgressIncrement, seekBar.getProgress());
oldProgress = seekBar.getProgress();
keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT);
- getInstrumentation().sendKeySync(keyEvent);
+ mInstrumentation.sendKeySync(keyEvent);
assertEquals(oldProgress - keyProgressIncrement, seekBar.getProgress());
}
- public void testSetMax() {
- MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity, null, R.style.TestProgressBar);
+ public void testAccessMax() {
+ AbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity, null, R.style.TestProgressBar);
int progress = 10;
myAbsSeekBar.setProgress(progress);
@@ -226,58 +243,70 @@
@UiThreadTest
public void testThumbTint() {
- mActivity.setContentView(R.layout.seekbar_layout);
-
- SeekBar inflatedView = (SeekBar) mActivity.findViewById(R.id.thumb_tint);
+ AbsSeekBar inflatedView = (AbsSeekBar) mActivity.findViewById(R.id.thumb_tint);
assertEquals("Thumb tint inflated correctly",
Color.WHITE, inflatedView.getThumbTintList().getDefaultColor());
assertEquals("Thumb tint mode inflated correctly",
PorterDuff.Mode.SRC_OVER, inflatedView.getThumbTintMode());
- MockDrawable thumb = new MockDrawable();
- SeekBar view = new SeekBar(mActivity);
+ Drawable mockThumb = spy(new ColorDrawable(Color.BLUE));
- view.setThumb(thumb);
- assertFalse("No thumb tint applied by default", thumb.hasCalledSetTint());
+ inflatedView.setThumb(mockThumb);
+ verify(mockThumb, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE));
- view.setThumbTintList(ColorStateList.valueOf(Color.WHITE));
- assertTrue("Thumb tint applied when setThumbTintList() called after setThumb()",
- thumb.hasCalledSetTint());
+ reset(mockThumb);
+ inflatedView.setThumbTintList(ColorStateList.valueOf(Color.RED));
+ verify(mockThumb, times(1)).setTintList(TestUtils.colorStateListOf(Color.RED));
- thumb.reset();
- view.setThumb(null);
- view.setThumb(thumb);
- assertTrue("Thumb tint applied when setThumbTintList() called before setThumb()",
- thumb.hasCalledSetTint());
+ inflatedView.setThumbTintMode(PorterDuff.Mode.DST_ATOP);
+ assertEquals("Thumb tint mode changed correctly",
+ PorterDuff.Mode.DST_ATOP, inflatedView.getThumbTintMode());
+
+ reset(mockThumb);
+ inflatedView.setThumb(null);
+ inflatedView.setThumb(mockThumb);
+ verify(mockThumb, times(1)).setTintList(TestUtils.colorStateListOf(Color.RED));
}
@UiThreadTest
public void testTickMarkTint() {
- mActivity.setContentView(R.layout.seekbar_layout);
-
- SeekBar inflatedView = (SeekBar) mActivity.findViewById(R.id.tick_mark_tint);
+ AbsSeekBar inflatedView = (AbsSeekBar) mActivity.findViewById(R.id.tick_mark_tint);
assertEquals("TickMark tint inflated correctly",
Color.WHITE, inflatedView.getTickMarkTintList().getDefaultColor());
assertEquals("TickMark tint mode inflated correctly",
PorterDuff.Mode.SRC_OVER, inflatedView.getTickMarkTintMode());
- MockDrawable tickMark = new MockDrawable();
- SeekBar view = new SeekBar(mActivity);
+ Drawable mockTickMark = spy(new ColorDrawable(Color.BLUE));
- view.setTickMark(tickMark);
- assertFalse("No tickMark tint applied by default", tickMark.hasCalledSetTint());
+ inflatedView.setTickMark(mockTickMark);
+ verify(mockTickMark, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE));
- view.setTickMarkTintList(ColorStateList.valueOf(Color.WHITE));
- assertTrue("TickMark tint applied when setTickMarkTintList() called after setTickMark()",
- tickMark.hasCalledSetTint());
+ reset(mockTickMark);
+ inflatedView.setTickMarkTintList(ColorStateList.valueOf(Color.RED));
+ verify(mockTickMark, times(1)).setTintList(TestUtils.colorStateListOf(Color.RED));
- tickMark.reset();
- view.setTickMark(null);
- view.setTickMark(tickMark);
- assertTrue("TickMark tint applied when setTickMarkTintList() called before setTickMark()",
- tickMark.hasCalledSetTint());
+ inflatedView.setTickMarkTintMode(PorterDuff.Mode.DARKEN);
+ assertEquals("TickMark tint mode changed correctly",
+ PorterDuff.Mode.DARKEN, inflatedView.getTickMarkTintMode());
+
+ reset(mockTickMark);
+ inflatedView.setTickMark(null);
+ inflatedView.setTickMark(mockTickMark);
+ verify(mockTickMark, times(1)).setTintList(TestUtils.colorStateListOf(Color.RED));
+ }
+
+ public void testAccessSplitTrack() {
+ AbsSeekBar inflatedView = (AbsSeekBar) mActivity.findViewById(R.id.tick_mark_tint);
+
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, inflatedView,
+ () -> inflatedView.setSplitTrack(true));
+ assertTrue(inflatedView.getSplitTrack());
+
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, inflatedView,
+ () -> inflatedView.setSplitTrack(false));
+ assertFalse(inflatedView.getSplitTrack());
}
private static class MyAbsSeekBar extends AbsSeekBar {
@@ -293,6 +322,10 @@
super(context, attrs, defStyle);
}
+ public MyAbsSeekBar(Context context, AttributeSet attrs, int defStyle, int defStyleRes) {
+ super(context, attrs, defStyle, defStyleRes);
+ }
+
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
@@ -303,45 +336,4 @@
return super.verifyDrawable(who);
}
}
-
- private static class MockDrawable extends Drawable {
- private int mAlpha;
- private boolean mCalledDraw = false;
- private boolean mCalledSetTint = false;
-
- @Override
- public void draw(Canvas canvas) { }
-
- public void reset() {
- mCalledDraw = false;
- mCalledSetTint = false;
- }
-
- @Override
- public int getOpacity() {
- return 0;
- }
-
- @Override
- public void setAlpha(int alpha) {
- mAlpha = alpha;
- }
-
- public int getAlpha() {
- return mAlpha;
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) { }
-
- @Override
- public void setTintList(ColorStateList tint) {
- super.setTintList(tint);
- mCalledSetTint = true;
- }
-
- public boolean hasCalledSetTint() {
- return mCalledSetTint;
- }
- }
}
diff --git a/tests/tests/widget/src/android/widget/cts/ActionMenuViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ActionMenuViewCtsActivity.java
new file mode 100644
index 0000000..1b58b63
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ActionMenuViewCtsActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.ActionMenuView;
+
+/**
+ * A minimal application for {@link ActionMenuView} test.
+ */
+public class ActionMenuViewCtsActivity extends Activity {
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.actionmenuview_layout);
+ }
+}
+
diff --git a/tests/tests/widget/src/android/widget/cts/ActionMenuViewTest.java b/tests/tests/widget/src/android/widget/cts/ActionMenuViewTest.java
new file mode 100644
index 0000000..6de7c39
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ActionMenuViewTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts;
+
+import android.app.Instrumentation;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ActionMenuView;
+import android.widget.Toolbar;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
+
+import static org.mockito.Mockito.*;
+
+@MediumTest
+public class ActionMenuViewTest
+ extends ActivityInstrumentationTestCase2<ActionMenuViewCtsActivity> {
+ private Instrumentation mInstrumentation;
+ private ActionMenuViewCtsActivity mActivity;
+ private ActionMenuView mActionMenuView;
+
+ public ActionMenuViewTest() {
+ super("android.widget.cts", ActionMenuViewCtsActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mInstrumentation = getInstrumentation();
+ mActivity = getActivity();
+ mActionMenuView = (ActionMenuView) mActivity.findViewById(R.id.action_menu_view);
+ }
+
+ public void testConstructor() {
+ new ActionMenuView(mActivity);
+
+ new ActionMenuView(mActivity, null);
+ }
+
+ public void testMenuContent() {
+ final Menu menu = mActionMenuView.getMenu();
+ assertNotNull(menu);
+
+ mInstrumentation.runOnMainSync(
+ () -> mActivity.getMenuInflater().inflate(
+ R.menu.toolbar_menu, menu));
+
+ assertEquals(6, menu.size());
+ assertEquals(R.id.action_highlight, menu.getItem(0).getItemId());
+ assertEquals(R.id.action_edit, menu.getItem(1).getItemId());
+ assertEquals(R.id.action_delete, menu.getItem(2).getItemId());
+ assertEquals(R.id.action_ignore, menu.getItem(3).getItemId());
+ assertEquals(R.id.action_share, menu.getItem(4).getItemId());
+ assertEquals(R.id.action_print, menu.getItem(5).getItemId());
+
+ ActionMenuView.OnMenuItemClickListener menuItemClickListener =
+ mock(ActionMenuView.OnMenuItemClickListener.class);
+ mActionMenuView.setOnMenuItemClickListener(menuItemClickListener);
+
+ menu.performIdentifierAction(R.id.action_highlight, 0);
+ verify(menuItemClickListener, times(1)).onMenuItemClick(
+ menu.findItem(R.id.action_highlight));
+
+ menu.performIdentifierAction(R.id.action_share, 0);
+ verify(menuItemClickListener, times(1)).onMenuItemClick(
+ menu.findItem(R.id.action_share));
+ }
+
+ public void testMenuOverflowShowHide() {
+ // Inflate menu and check that we're not showing overflow menu yet
+ mInstrumentation.runOnMainSync(
+ () -> mActivity.getMenuInflater().inflate(
+ R.menu.toolbar_menu, mActionMenuView.getMenu()));
+ assertFalse(mActionMenuView.isOverflowMenuShowing());
+
+ // Ask to show overflow menu and check that it's showing
+ mInstrumentation.runOnMainSync(() -> mActionMenuView.showOverflowMenu());
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mActionMenuView.isOverflowMenuShowing());
+
+ // Ask to hide the overflow menu and check that it's not showing
+ mInstrumentation.runOnMainSync(() -> mActionMenuView.hideOverflowMenu());
+ mInstrumentation.waitForIdleSync();
+ assertFalse(mActionMenuView.isOverflowMenuShowing());
+ }
+
+ public void testMenuOverflowSubmenu() {
+ // Inflate menu and check that we're not showing overflow menu yet
+ mInstrumentation.runOnMainSync(
+ () -> mActivity.getMenuInflater().inflate(
+ R.menu.toolbar_menu, mActionMenuView.getMenu()));
+ assertFalse(mActionMenuView.isOverflowMenuShowing());
+
+ // Ask to show overflow menu and check that it's showing
+ mInstrumentation.runOnMainSync(() -> mActionMenuView.showOverflowMenu());
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mActionMenuView.isOverflowMenuShowing());
+
+ // Register a mock menu item click listener on the toolbar
+ ActionMenuView.OnMenuItemClickListener menuItemClickListener =
+ mock(ActionMenuView.OnMenuItemClickListener.class);
+ mActionMenuView.setOnMenuItemClickListener(menuItemClickListener);
+
+ final Menu menu = mActionMenuView.getMenu();
+
+ // Ask to "perform" the share action and check that the menu click listener has
+ // been notified
+ mInstrumentation.runOnMainSync(() -> menu.performIdentifierAction(R.id.action_share, 0));
+ verify(menuItemClickListener, times(1)).onMenuItemClick(
+ menu.findItem(R.id.action_share));
+
+ // Ask to dismiss all the popups and check that we're not showing the overflow menu
+ mInstrumentation.runOnMainSync(() -> mActionMenuView.dismissPopupMenus());
+ mInstrumentation.waitForIdleSync();
+ assertFalse(mActionMenuView.isOverflowMenuShowing());
+ }
+
+ public void testMenuOverflowIcon() {
+ // Inflate menu and check that we're not showing overflow menu yet
+ mInstrumentation.runOnMainSync(
+ () -> mActivity.getMenuInflater().inflate(
+ R.menu.toolbar_menu, mActionMenuView.getMenu()));
+
+ final Drawable overflowIcon = mActivity.getDrawable(R.drawable.icon_red);
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mActionMenuView,
+ () -> mActionMenuView.setOverflowIcon(overflowIcon));
+
+ final Drawable toolbarOverflowIcon = mActionMenuView.getOverflowIcon();
+ TestUtils.assertAllPixelsOfColor("Overflow icon is red", toolbarOverflowIcon,
+ toolbarOverflowIcon.getIntrinsicWidth(), toolbarOverflowIcon.getIntrinsicHeight(),
+ true, Color.RED, 1, false);
+ }
+
+ public void testPopupTheme() {
+ mInstrumentation.runOnMainSync(() -> {
+ mActivity.getMenuInflater().inflate(R.menu.toolbar_menu, mActionMenuView.getMenu());
+ mActionMenuView.setPopupTheme(R.style.ToolbarPopupTheme_Test);
+ });
+ assertEquals(R.style.ToolbarPopupTheme_Test, mActionMenuView.getPopupTheme());
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java b/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
index 1b9137f..72ecf7e 100644
--- a/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
@@ -16,12 +16,12 @@
package android.widget.cts;
-import org.xmlpull.v1.XmlPullParser;
-
-import android.app.Activity;
+import android.app.Instrumentation;
import android.content.Context;
import android.os.Parcelable;
+import android.provider.Settings;
import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.util.Xml;
@@ -31,17 +31,17 @@
import android.view.animation.LayoutAnimationController;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.AdapterView.OnItemLongClickListener;
-import android.widget.AdapterView.OnItemSelectedListener;
-import android.provider.Settings;
+import android.widget.cts.util.ViewTestUtils;
-import android.widget.cts.R;
+import org.xmlpull.v1.XmlPullParser;
+import static org.mockito.Mockito.*;
+@SmallTest
public class AdapterViewTest extends ActivityInstrumentationTestCase2<AdapterViewCtsActivity> {
private final static int INVALID_ID = -1;
@@ -51,7 +51,7 @@
final String[] FRUIT = { "1", "2", "3", "4", "5", "6", "7", "8" };
- private Activity mActivity;
+ private AdapterViewCtsActivity mActivity;
private AdapterView<ListAdapter> mAdapterView;
public AdapterViewTest() {
@@ -250,47 +250,67 @@
}
public void testAccessOnItemClickAndLongClickListener() {
- MockOnItemClickListener clickListener = new MockOnItemClickListener();
- MockOnItemLongClickListener longClickListener = new MockOnItemLongClickListener();
+ AdapterView.OnItemClickListener mockClickListener =
+ mock(AdapterView.OnItemClickListener.class);
+ AdapterView.OnItemLongClickListener mockLongClickListener =
+ mock(AdapterView.OnItemLongClickListener.class);
+ when(mockLongClickListener.onItemLongClick(
+ any(AdapterView.class), any(View.class), anyInt(), anyLong())).thenReturn(true);
+
+ assertNull(mAdapterView.getOnItemLongClickListener());
+ assertNull(mAdapterView.getOnItemClickListener());
assertFalse(mAdapterView.performItemClick(null, 0, 0));
- mAdapterView.setOnItemClickListener(clickListener);
- mAdapterView.setOnItemLongClickListener(longClickListener);
+ mAdapterView.setOnItemClickListener(mockClickListener);
+ mAdapterView.setOnItemLongClickListener(mockLongClickListener);
+ assertEquals(mockLongClickListener, mAdapterView.getOnItemLongClickListener());
- assertFalse(clickListener.isClicked());
+ verifyZeroInteractions(mockClickListener);
assertTrue(mAdapterView.performItemClick(null, 0, 0));
- assertTrue(clickListener.isClicked());
+ verify(mockClickListener, times(1)).onItemClick(eq(mAdapterView), any(View.class),
+ eq(0), eq(0L));
setArrayAdapter(mAdapterView);
- assertFalse(longClickListener.isClicked());
+ verifyZeroInteractions(mockLongClickListener);
mAdapterView.layout(0, 0, LAYOUT_WIDTH, LAYOUT_HEIGHT);
assertTrue(mAdapterView.showContextMenuForChild(mAdapterView.getChildAt(0)));
- assertTrue(longClickListener.isClicked());
+ verify(mockLongClickListener, times(1)).onItemLongClick(eq(mAdapterView), any(View.class),
+ eq(0), eq(0L));
}
public void testAccessOnItemSelectedListener() {
- // FIXME: we can not select the item in touch mode, how can we change the mode to test
- setArrayAdapter(mAdapterView);
- MockOnItemSelectedListener selectedListener = new MockOnItemSelectedListener();
- mAdapterView.setOnItemSelectedListener(selectedListener);
+ mAdapterView = mActivity.getListView();
+ final Instrumentation instrumentation = getInstrumentation();
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mAdapterView,
+ () -> mAdapterView.setLayoutParams(new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT)));
-// mAdapterView.layout(0, 0, LAYOUT_WIDTH, LAYOUT_HEIGHT);
-//
-// assertFalse(selectedListener.isItemSelected());
-// assertFalse(selectedListener.isNothingSelected());
-//
-// mAdapterView.setSelection(1);
-// assertTrue(selectedListener.isItemSelected());
-// assertFalse(selectedListener.isNothingSelected());
-//
-// mAdapterView.setSelection(-1);
-// assertTrue(selectedListener.isItemSelected());
-// assertTrue(selectedListener.isNothingSelected());
-//
-// mAdapterView.setSelection(FRUIT.length);
-// assertTrue(selectedListener.isItemSelected());
-// assertTrue(selectedListener.isNothingSelected());
+ instrumentation.runOnMainSync(() -> setArrayAdapter(mAdapterView));
+
+ AdapterView.OnItemSelectedListener mockSelectedListener =
+ mock(AdapterView.OnItemSelectedListener.class);
+ mAdapterView.setOnItemSelectedListener(mockSelectedListener);
+ assertEquals(mockSelectedListener, mAdapterView.getOnItemSelectedListener());
+
+ verifyZeroInteractions(mockSelectedListener);
+
+ // Select item #1 and verify that the listener has been notified
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mAdapterView,
+ () -> mAdapterView.setSelection(1));
+ verify(mockSelectedListener, times(1)).onItemSelected(eq(mAdapterView), any(View.class),
+ eq(1), eq(1L));
+ verifyNoMoreInteractions(mockSelectedListener);
+
+ // Select last item and verify that the listener has been notified
+ reset(mockSelectedListener);
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mAdapterView,
+ () -> mAdapterView.setSelection(FRUIT.length - 1));
+ verify(mockSelectedListener, times(1)).onItemSelected(
+ eq(mAdapterView), any(View.class), eq(FRUIT.length - 1),
+ eq((long) FRUIT.length - 1));
+ verifyNoMoreInteractions(mockSelectedListener);
}
/*
@@ -459,62 +479,7 @@
}
private void setArrayAdapter(AdapterView<ListAdapter> adapterView) {
- ((ListView) adapterView).setAdapter(new ArrayAdapter<String>(
+ adapterView.setAdapter(new ArrayAdapter<>(
mActivity, R.layout.adapterview_layout, FRUIT));
}
-
- /**
- * this is a mock item click listener for check out call back
- */
- private class MockOnItemClickListener implements OnItemClickListener {
- private boolean mClicked;
-
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- mClicked = true;
- }
-
- protected boolean isClicked() {
- return mClicked;
- }
- }
-
- /**
- * this is a mock long item click listener for check out call back
- */
- private class MockOnItemLongClickListener implements OnItemLongClickListener {
- private boolean mClicked;
-
- public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
- mClicked = true;
- return true;
- }
-
- protected boolean isClicked() {
- return mClicked;
- }
- }
-
- /**
- * this is a mock item selected listener for check out call lback
- */
- private class MockOnItemSelectedListener implements OnItemSelectedListener {
- private boolean mIsItemSelected;
- private boolean mIsNothingSelected;
-
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- mIsItemSelected = true;
- }
-
- public void onNothingSelected(AdapterView<?> parent) {
- mIsNothingSelected = true;
- }
-
- protected boolean isItemSelected() {
- return mIsItemSelected;
- }
-
- protected boolean isNothingSelected() {
- return mIsNothingSelected;
- }
- }
}
diff --git a/tests/tests/widget/src/android/widget/cts/ArrayAdapterTest.java b/tests/tests/widget/src/android/widget/cts/ArrayAdapterTest.java
index 03677f2..2cb8ee4 100644
--- a/tests/tests/widget/src/android/widget/cts/ArrayAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ArrayAdapterTest.java
@@ -25,16 +25,17 @@
import android.database.DataSetObserver;
import android.test.InstrumentationTestCase;
import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.TextView;
-import android.widget.cts.R;
+import static org.mockito.Mockito.*;
-
+@SmallTest
public class ArrayAdapterTest extends InstrumentationTestCase {
- private static final int INVALD_ID = -1;
+ private static final int INVALID_ID = -1;
private static final String STR1 = "string1";
private static final String STR2 = "string2";
private static final String STR3 = "string3";
@@ -46,30 +47,30 @@
protected void setUp() throws Exception {
super.setUp();
mContext = getInstrumentation().getTargetContext();
- mArrayAdapter = new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line);
+ mArrayAdapter = new ArrayAdapter<>(mContext, R.layout.simple_dropdown_item_1line);
}
public void testConstructor() {
new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line);
- new ArrayAdapter<String>(mContext, INVALD_ID);// invalid resource id
+ new ArrayAdapter<String>(mContext, INVALID_ID); // invalid resource id
new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, R.id.text1);
- new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, INVALD_ID);
+ new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, INVALID_ID);
- new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line,
+ new ArrayAdapter<>(mContext, R.layout.simple_dropdown_item_1line,
new String[] {"str1", "str2"});
- new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, R.id.text1,
+ new ArrayAdapter<>(mContext, R.layout.simple_dropdown_item_1line, R.id.text1,
new String[] {"str1", "str2"});
- List<String> list = new ArrayList<String>();
+ List<String> list = new ArrayList<>();
list.add(STR1);
list.add(STR2);
- new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, list);
+ new ArrayAdapter<>(mContext, R.layout.simple_dropdown_item_1line, list);
- new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, R.id.text1, list);
+ new ArrayAdapter<>(mContext, R.layout.simple_dropdown_item_1line, R.id.text1, list);
// invalid input
try {
@@ -81,46 +82,46 @@
}
public void testDataChangeEvent() {
- final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver();
+ final DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
mArrayAdapter.registerDataSetObserver(mockDataSetObserver);
// enable automatically notifying.
mArrayAdapter.setNotifyOnChange(true);
- assertEquals(0, mockDataSetObserver.getCalledOnChangedCount());
+ verifyZeroInteractions(mockDataSetObserver);
mArrayAdapter.add(STR1);
assertEquals(1, mArrayAdapter.getCount());
- assertEquals(1, mockDataSetObserver.getCalledOnChangedCount());
+ verify(mockDataSetObserver, times(1)).onChanged();
mArrayAdapter.add(STR2);
assertEquals(2, mArrayAdapter.getCount());
- assertEquals(2, mockDataSetObserver.getCalledOnChangedCount());
+ verify(mockDataSetObserver, times(2)).onChanged();
// reset data
mArrayAdapter.clear();
// clear notify changed
- assertEquals(3, mockDataSetObserver.getCalledOnChangedCount());
+ verify(mockDataSetObserver, times(3)).onChanged();
assertEquals(0, mArrayAdapter.getCount());
// if empty before, clear also notify changed
mArrayAdapter.clear();
- assertEquals(4, mockDataSetObserver.getCalledOnChangedCount());
- mockDataSetObserver.clearCount();
- assertEquals(0, mockDataSetObserver.getCalledOnChangedCount());
+ verify(mockDataSetObserver, times(4)).onChanged();
+
+ reset(mockDataSetObserver);
// disable auto notify
mArrayAdapter.setNotifyOnChange(false);
mArrayAdapter.add(STR3);
assertEquals(1, mArrayAdapter.getCount());
- assertEquals(0, mockDataSetObserver.getCalledOnChangedCount());
+ verifyZeroInteractions(mockDataSetObserver);
// manually notify
mArrayAdapter.notifyDataSetChanged();
- assertEquals(1, mockDataSetObserver.getCalledOnChangedCount());
+ verify(mockDataSetObserver, times(1)).onChanged();
// no data changed, but force notify
mArrayAdapter.notifyDataSetChanged();
- assertEquals(2, mockDataSetObserver.getCalledOnChangedCount());
+ verify(mockDataSetObserver, times(2)).onChanged();
// once called notify, auto notify enabled
mArrayAdapter.add(STR3);
- assertEquals(3, mockDataSetObserver.getCalledOnChangedCount());
+ verify(mockDataSetObserver, times(3)).onChanged();
}
public void testAccessView() {
@@ -202,7 +203,7 @@
// expected exception
}
- mArrayAdapter.setDropDownViewResource(INVALD_ID);
+ mArrayAdapter.setDropDownViewResource(INVALID_ID);
}
public void testAccessDropDownViewTheme() {
@@ -217,13 +218,13 @@
*/
public void testInsert() {
mArrayAdapter.setNotifyOnChange(true);
- final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver();
+ final DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
mArrayAdapter.registerDataSetObserver(mockDataSetObserver);
mArrayAdapter.insert(STR1, 0);
assertEquals(1, mArrayAdapter.getCount());
assertEquals(0, mArrayAdapter.getPosition(STR1));
- assertEquals(1, mockDataSetObserver.getCalledOnChangedCount());
+ verify(mockDataSetObserver, times(1)).onChanged();
mArrayAdapter.insert(STR2, 0);
assertEquals(2, mArrayAdapter.getCount());
@@ -294,8 +295,7 @@
// test invalid input
assertEquals(-1, mArrayAdapter.getItemId(-1));
- assertEquals(mArrayAdapter.getCount(),
- mArrayAdapter.getItemId(mArrayAdapter.getCount()));
+ assertEquals(mArrayAdapter.getCount(), mArrayAdapter.getItemId(mArrayAdapter.getCount()));
}
/*
@@ -322,23 +322,22 @@
* remove first one if duplicated string in the array
*/
public void testRemove() {
- final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver();
+ final DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
mArrayAdapter.registerDataSetObserver(mockDataSetObserver);
mArrayAdapter.setNotifyOnChange(true);
// remove the not exist one
assertEquals(0, mArrayAdapter.getCount());
- assertEquals(0, mockDataSetObserver.getCalledOnChangedCount());
+ verifyZeroInteractions(mockDataSetObserver);
// remove the item not exist also notify change
mArrayAdapter.remove(STR1);
- assertEquals(1, mockDataSetObserver.getCalledOnChangedCount());
+ verify(mockDataSetObserver, times(1)).onChanged();
mArrayAdapter.add(STR1);
mArrayAdapter.add(STR2);
mArrayAdapter.add(STR3);
mArrayAdapter.add(STR2);
- mockDataSetObserver.clearCount();
- assertEquals(0, mockDataSetObserver.getCalledOnChangedCount());
+ reset(mockDataSetObserver);
assertEquals(4, mArrayAdapter.getCount());
mArrayAdapter.remove(STR1);
@@ -346,11 +345,11 @@
assertEquals(-1, mArrayAdapter.getPosition(STR1));
assertEquals(0, mArrayAdapter.getPosition(STR2));
assertEquals(1, mArrayAdapter.getPosition(STR3));
- assertEquals(1, mockDataSetObserver.getCalledOnChangedCount());
+ verify(mockDataSetObserver, times(1)).onChanged();
mArrayAdapter.remove(STR2);
assertEquals(2, mArrayAdapter.getCount());
- // remove the first one if dumplicated
+ // remove the first one if duplicated
assertEquals(1, mArrayAdapter.getPosition(STR2));
assertEquals(0, mArrayAdapter.getPosition(STR3));
@@ -376,30 +375,26 @@
}
try {
- ArrayAdapter.createFromResource(mContext, INVALD_ID, R.layout.simple_spinner_item);
+ ArrayAdapter.createFromResource(mContext, INVALID_ID, R.layout.simple_spinner_item);
fail("should throw NullPointerException");
} catch (NullPointerException e) {
// expected exception
}
- ArrayAdapter.createFromResource(mContext, R.array.string, INVALD_ID);
+ ArrayAdapter.createFromResource(mContext, R.array.string, INVALID_ID);
}
public void testSort() {
- final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver();
+ final DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
mArrayAdapter.registerDataSetObserver(mockDataSetObserver);
mArrayAdapter.setNotifyOnChange(true);
- assertEquals(0, mockDataSetObserver.getCalledOnChangedCount());
+ verifyZeroInteractions(mockDataSetObserver);
- mArrayAdapter.sort( new Comparator<String>() {
- public int compare(String o1, String o2) {
- return 0;
- }
- });
- assertEquals(1, mockDataSetObserver.getCalledOnChangedCount());
+ mArrayAdapter.sort((String o1, String o2) -> 0);
+ verify(mockDataSetObserver, times(1)).onChanged();
mArrayAdapter.sort(null);
- assertEquals(2, mockDataSetObserver.getCalledOnChangedCount());
+ verify(mockDataSetObserver, times(2)).onChanged();
}
/**
@@ -408,7 +403,7 @@
*/
public void testAdd() {
mArrayAdapter.setNotifyOnChange(true);
- final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver();
+ final DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
mArrayAdapter.registerDataSetObserver(mockDataSetObserver);
mArrayAdapter.clear();
@@ -427,10 +422,10 @@
*/
public void testAddAllCollection() {
mArrayAdapter.setNotifyOnChange(true);
- final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver();
+ final DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
mArrayAdapter.registerDataSetObserver(mockDataSetObserver);
- List<String> list = new ArrayList<String>();
+ List<String> list = new ArrayList<>();
list.add("");
list.add("hello");
list.add("android");
@@ -454,7 +449,7 @@
*/
public void testAddAllParams() {
mArrayAdapter.setNotifyOnChange(true);
- final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver();
+ final DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
mArrayAdapter.registerDataSetObserver(mockDataSetObserver);
mArrayAdapter.clear();
@@ -468,35 +463,4 @@
assertEquals(mArrayAdapter.getItem(3), "unit");
assertEquals(mArrayAdapter.getItem(4), "test");
}
-
- private static class MockDataSetObserver extends DataSetObserver {
-
- private int mCalledOnChangedCount;
- private int mOnCalledInvalidatedCount;
-
- public MockDataSetObserver() {
- clearCount();
- }
-
- public int getCalledOnChangedCount() {
- return mCalledOnChangedCount;
- }
-
- public int getCalledOnInvalidatedCount() {
- return mOnCalledInvalidatedCount;
- }
-
- public void clearCount() {
- mCalledOnChangedCount = 0;
- mOnCalledInvalidatedCount = 0;
- }
-
- public void onChanged() {
- mCalledOnChangedCount++;
- }
-
- public void onInvalidated() {
- mOnCalledInvalidatedCount++;
- }
- }
}
diff --git a/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java b/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
index eb22d6b..520b430 100644
--- a/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
@@ -16,21 +16,22 @@
package android.widget.cts;
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.app.Activity;
import android.app.Instrumentation;
import android.app.UiModeManager;
import android.content.Context;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.cts.util.PollingCheck;
+import android.graphics.Color;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.text.Editable;
+import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Xml;
import android.view.KeyCharacterMap;
@@ -40,37 +41,30 @@
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
+import android.widget.AutoCompleteTextView.Validator;
import android.widget.Filter;
import android.widget.Filterable;
-import android.widget.AutoCompleteTextView.Validator;
+import android.widget.cts.util.TestUtils;
+import org.xmlpull.v1.XmlPullParser;
-import java.io.IOException;
+import static org.mockito.Mockito.*;
+@MediumTest
public class AutoCompleteTextViewTest extends
ActivityInstrumentationTestCase2<AutoCompleteCtsActivity> {
+ private final static String[] WORDS =
+ new String[] { "testOne", "testTwo", "testThree", "testFour" };
+ private final static String STRING_TEST = "To be tested";
+ private final static String STRING_VALIDATED = "String Validated";
+ private final static String STRING_CHECK = "To be checked";
- /**
- * Instantiates a new text view test.
- */
- public AutoCompleteTextViewTest() {
- super("android.widget.cts", AutoCompleteCtsActivity.class);
- }
-
- /** The m activity. */
private Activity mActivity;
-
- /** The m instrumentation. */
private Instrumentation mInstrumentation;
private AutoCompleteTextView mAutoCompleteTextView;
private boolean mNumeric = false;
- ArrayAdapter<String> mAdapter;
- private final String[] WORDS = new String[] { "testOne", "testTwo", "testThree", "testFour" };
- boolean isOnFilterComplete = false;
- final String STRING_TEST = "To be tested";
- final String STRING_VALIDATED = "String Validated";
- final String STRING_CHECK = "To be checked";
- final String STRING_APPEND = "and be appended";
- Validator mValidator = new Validator() {
+ private ArrayAdapter<String> mAdapter;
+
+ private final Validator mValidator = new Validator() {
public CharSequence fixText(CharSequence invalidText) {
return STRING_VALIDATED;
}
@@ -80,6 +74,36 @@
}
};
+ protected class MyTextWatcher implements TextWatcher {
+ private CharSequence mExpectedAfter;
+
+ public MyTextWatcher(CharSequence expectedAfter) {
+ mExpectedAfter = expectedAfter;
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ assertEquals(mExpectedAfter.toString(), s.toString());
+ // This watcher is expected to be notified in the middle of completion
+ assertTrue(mAutoCompleteTextView.isPerformingCompletion());
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ }
+ }
+
+ /**
+ * Instantiates a new text view test.
+ */
+ public AutoCompleteTextViewTest() {
+ super("android.widget.cts", AutoCompleteCtsActivity.class);
+ }
+
/*
* (non-Javadoc)
*
@@ -89,12 +113,8 @@
protected void setUp() throws Exception {
super.setUp();
mActivity = getActivity();
- new PollingCheck() {
- @Override
- protected boolean check() {
- return mActivity.hasWindowFocus();
- }
- }.run();
+ PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
+
mInstrumentation = getInstrumentation();
mAutoCompleteTextView = (AutoCompleteTextView) mActivity
.findViewById(R.id.autocompletetv_edit);
@@ -116,20 +136,32 @@
public void testConstructor() {
XmlPullParser parser;
- // new the AutoCompleteTextView instance
new AutoCompleteTextView(mActivity);
+ new AutoCompleteTextView(mActivity, null);
+ new AutoCompleteTextView(mActivity, null, android.R.attr.autoCompleteTextViewStyle);
+ new AutoCompleteTextView(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_AutoCompleteTextView);
+ new AutoCompleteTextView(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_Light_AutoCompleteTextView);
+ new AutoCompleteTextView(mActivity, null, 0,
+ android.R.style.Widget_Material_AutoCompleteTextView);
+ new AutoCompleteTextView(mActivity, null, 0,
+ android.R.style.Widget_Material_Light_AutoCompleteTextView);
+
+ final Resources.Theme popupTheme = mActivity.getResources().newTheme();
+ popupTheme.applyStyle(android.R.style.Theme_Material, true);
+ new AutoCompleteTextView(mActivity, null, 0,
+ android.R.style.Widget_Material_Light_AutoCompleteTextView, popupTheme);
// new the AutoCompleteTextView instance
parser = mActivity.getResources().getXml(R.layout.simple_dropdown_item_1line);
AttributeSet attributeSet = Xml.asAttributeSet(parser);
new AutoCompleteTextView(mActivity, attributeSet);
- new AutoCompleteTextView(mActivity, null);
// new the AutoCompleteTextView instance
parser = mActivity.getResources().getXml(R.layout.framelayout_layout);
attributeSet = Xml.asAttributeSet(parser);
new AutoCompleteTextView(mActivity, attributeSet, 0);
- new AutoCompleteTextView(mActivity, null, 0);
// Test constructor with null Context, in fact, previous two functions will
// finally invoke this version.
try {
@@ -145,38 +177,39 @@
new AutoCompleteTextView(mActivity, null, -1);
}
- public void testEnoughToFilter() throws Throwable {
+ public void testEnoughToFilter() {
mAutoCompleteTextView.setThreshold(3);
assertEquals(3, mAutoCompleteTextView.getThreshold());
- runTestOnUiThread(new Runnable() {
- public void run() {
- String testString = "TryToTest";
- mAutoCompleteTextView.setText(testString);
- }
- });
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setText("TryToTest"));
mInstrumentation.waitForIdleSync();
assertTrue(mAutoCompleteTextView.enoughToFilter());
- runTestOnUiThread(new Runnable() {
- public void run() {
- String testString = "No";
- mAutoCompleteTextView.setText(testString);
- }
- });
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setText("No"));
mInstrumentation.waitForIdleSync();
assertFalse(mAutoCompleteTextView.enoughToFilter());
}
- @UiThreadTest
public void testAccessAdapter() {
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setAdapter(null));
+ assertNull(mAutoCompleteTextView.getAdapter());
+
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setAdapter(mAdapter));
+ assertSame(mAdapter, mAutoCompleteTextView.getAdapter());
+
+ // Re-set adapter to null
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setAdapter(null));
+ assertNull(mAutoCompleteTextView.getAdapter());
+ }
+
+ @UiThreadTest
+ public void testAccessFilter() {
MockAutoCompleteTextView autoCompleteTextView = new MockAutoCompleteTextView(mActivity);
// Set Threshold to 4 characters
autoCompleteTextView.setThreshold(4);
- ArrayAdapter<String> adapter = null;
- autoCompleteTextView.setAdapter(adapter);
+ autoCompleteTextView.setAdapter(null);
assertNull(autoCompleteTextView.getAdapter());
assertNull(autoCompleteTextView.getFilter());
@@ -187,49 +220,51 @@
assertSame(filter, autoCompleteTextView.getFilter());
// Re-set adapter to null
- autoCompleteTextView.setAdapter(adapter);
+ autoCompleteTextView.setAdapter(null);
assertNull(autoCompleteTextView.getAdapter());
assertNull(autoCompleteTextView.getFilter());
}
- @SuppressWarnings("deprecation")
public void testAccessItemClickListener() {
- final MockOnItemClickListener testOnItemClickListener = new MockOnItemClickListener();
+ final AdapterView.OnItemClickListener mockItemClickListener =
+ mock(AdapterView.OnItemClickListener.class);
// To ensure null listener
mAutoCompleteTextView.setOnItemClickListener(null);
assertNull(mAutoCompleteTextView.getItemClickListener());
assertNull(mAutoCompleteTextView.getOnItemClickListener());
- assertNotNull(testOnItemClickListener);
- mAutoCompleteTextView.setOnItemClickListener(testOnItemClickListener);
- assertSame(testOnItemClickListener, mAutoCompleteTextView.getItemClickListener());
- assertSame(testOnItemClickListener, mAutoCompleteTextView.getOnItemClickListener());
+ mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
+ assertSame(mockItemClickListener, mAutoCompleteTextView.getItemClickListener());
+ assertSame(mockItemClickListener, mAutoCompleteTextView.getOnItemClickListener());
+ verifyZeroInteractions(mockItemClickListener);
// re-clear listener by setOnItemClickListener
mAutoCompleteTextView.setOnItemClickListener(null);
assertNull(mAutoCompleteTextView.getItemClickListener());
assertNull(mAutoCompleteTextView.getOnItemClickListener());
+ verifyZeroInteractions(mockItemClickListener);
}
- @SuppressWarnings("deprecation")
public void testAccessItemSelectedListener() {
- MockOnItemSelectedListener testOnItemSelectedListener = new MockOnItemSelectedListener();
+ final AdapterView.OnItemSelectedListener mockItemSelectedListener =
+ mock(AdapterView.OnItemSelectedListener.class);
// To ensure null listener
mAutoCompleteTextView.setOnItemSelectedListener(null);
assertNull(mAutoCompleteTextView.getItemSelectedListener());
assertNull(mAutoCompleteTextView.getOnItemSelectedListener());
- assertNotNull(testOnItemSelectedListener);
- mAutoCompleteTextView.setOnItemSelectedListener(testOnItemSelectedListener);
- assertSame(testOnItemSelectedListener, mAutoCompleteTextView.getItemSelectedListener());
- assertSame(testOnItemSelectedListener, mAutoCompleteTextView.getOnItemSelectedListener());
+ mAutoCompleteTextView.setOnItemSelectedListener(mockItemSelectedListener);
+ assertSame(mockItemSelectedListener, mAutoCompleteTextView.getItemSelectedListener());
+ assertSame(mockItemSelectedListener, mAutoCompleteTextView.getOnItemSelectedListener());
+ verifyZeroInteractions(mockItemSelectedListener);
//re-clear listener by setOnItemClickListener
mAutoCompleteTextView.setOnItemSelectedListener(null);
assertNull(mAutoCompleteTextView.getItemSelectedListener());
assertNull(mAutoCompleteTextView.getOnItemSelectedListener());
+ verifyZeroInteractions(mockItemSelectedListener);
}
@UiThreadTest
@@ -247,73 +282,130 @@
@UiThreadTest
public void testOnTextChanged() {
- MockAutoCompleteTextView autoCompleteTextView = new MockAutoCompleteTextView(mActivity);
+ final TextWatcher mockTextWatcher = mock(TextWatcher.class);
+ mAutoCompleteTextView.addTextChangedListener(mockTextWatcher);
+ verify(mockTextWatcher, never()).onTextChanged(any(CharSequence.class),
+ anyInt(), anyInt(), anyInt());
- assertFalse(autoCompleteTextView.isOnTextChanged());
- assertEquals("", autoCompleteTextView.getLastChangeText());
- assertEquals("", autoCompleteTextView.getText().toString());
- assertEquals(0, autoCompleteTextView.getStart());
- assertEquals(0, autoCompleteTextView.getBefore());
- assertEquals(0, autoCompleteTextView.getAfter());
-
- autoCompleteTextView.setText(STRING_TEST);
- assertEquals(STRING_TEST, autoCompleteTextView.getText().toString());
- assertTrue(autoCompleteTextView.isOnTextChanged());
- assertEquals(STRING_TEST, autoCompleteTextView.getLastChangeText());
- assertEquals(0, autoCompleteTextView.getStart());
- assertEquals(0, autoCompleteTextView.getBefore());
- assertEquals(STRING_TEST.length(), autoCompleteTextView.getAfter());
+ mAutoCompleteTextView.setText(STRING_TEST);
+ verify(mockTextWatcher, times(1)).onTextChanged(TestUtils.sameCharSequence(STRING_TEST),
+ eq(0), eq(0), eq(STRING_TEST.length()));
// Test replacing text.
- autoCompleteTextView.resetStatus();
- autoCompleteTextView.setText(STRING_CHECK);
- assertEquals(STRING_CHECK, autoCompleteTextView.getText().toString());
- assertEquals(STRING_CHECK, autoCompleteTextView.getLastChangeText());
- assertEquals(0, autoCompleteTextView.getStart());
- assertEquals(STRING_TEST.length(), autoCompleteTextView.getBefore());
- assertEquals(STRING_CHECK.length(), autoCompleteTextView.getAfter());
+ mAutoCompleteTextView.setText(STRING_CHECK);
+ verify(mockTextWatcher, times(1)).onTextChanged(TestUtils.sameCharSequence(STRING_CHECK),
+ eq(0), eq(STRING_TEST.length()), eq(STRING_CHECK.length()));
}
- @UiThreadTest
- public void testPopupWindow() throws XmlPullParserException, IOException {
- assertFalse(mAutoCompleteTextView.isPopupShowing());
- mAutoCompleteTextView.showDropDown();
- assertTrue(mAutoCompleteTextView.isPopupShowing());
+ public void testPopupWindow() {
+ final AutoCompleteTextView.OnDismissListener mockDismissListener =
+ mock(AutoCompleteTextView.OnDismissListener.class);
+ mAutoCompleteTextView.setOnDismissListener(mockDismissListener);
- mAutoCompleteTextView.dismissDropDown();
assertFalse(mAutoCompleteTextView.isPopupShowing());
-
- mAutoCompleteTextView.showDropDown();
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.showDropDown());
assertTrue(mAutoCompleteTextView.isPopupShowing());
+ verifyZeroInteractions(mockDismissListener);
+
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.dismissDropDown());
+ assertFalse(mAutoCompleteTextView.isPopupShowing());
+ verify(mockDismissListener, times(1)).onDismiss();
+
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.showDropDown());
+ assertTrue(mAutoCompleteTextView.isPopupShowing());
+ verify(mockDismissListener, times(1)).onDismiss();
final MockValidator validator = new MockValidator();
mAutoCompleteTextView.setValidator(validator);
- mAutoCompleteTextView.requestFocus();
- mAutoCompleteTextView.showDropDown();
- assertTrue(mAutoCompleteTextView.isPopupShowing());
- mAutoCompleteTextView.setText(STRING_TEST);
+ mInstrumentation.runOnMainSync(() -> {
+ mAutoCompleteTextView.requestFocus();
+ mAutoCompleteTextView.showDropDown();
+ mAutoCompleteTextView.setText(STRING_TEST);
+ });
assertEquals(STRING_TEST, mAutoCompleteTextView.getText().toString());
+
// clearFocus will trigger onFocusChanged, and onFocusChanged will validate the text.
- mAutoCompleteTextView.clearFocus();
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.clearFocus());
assertFalse(mAutoCompleteTextView.isPopupShowing());
assertEquals(STRING_VALIDATED, mAutoCompleteTextView.getText().toString());
+ verify(mockDismissListener, times(2)).onDismiss();
+
+ verifyNoMoreInteractions(mockDismissListener);
+ }
+
+ public void testDropDownMetrics() {
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setAdapter(mAdapter));
+
+ final Resources res = mActivity.getResources();
+ final int dropDownWidth =
+ res.getDimensionPixelSize(R.dimen.autocomplete_textview_dropdown_width);
+ final int dropDownHeight =
+ res.getDimensionPixelSize(R.dimen.autocomplete_textview_dropdown_height);
+ final int dropDownOffsetHorizontal =
+ res.getDimensionPixelSize(R.dimen.autocomplete_textview_dropdown_offset_h);
+ final int dropDownOffsetVertical =
+ res.getDimensionPixelSize(R.dimen.autocomplete_textview_dropdown_offset_v);
+
+ mInstrumentation.runOnMainSync(() -> {
+ mAutoCompleteTextView.setDropDownWidth(dropDownWidth);
+ mAutoCompleteTextView.setDropDownHeight(dropDownHeight);
+ mAutoCompleteTextView.setDropDownHorizontalOffset(dropDownOffsetHorizontal);
+ mAutoCompleteTextView.setDropDownVerticalOffset(dropDownOffsetVertical);
+
+ mAutoCompleteTextView.showDropDown();
+ });
+
+ assertEquals(dropDownWidth, mAutoCompleteTextView.getDropDownWidth());
+ assertEquals(dropDownHeight, mAutoCompleteTextView.getDropDownHeight());
+ assertEquals(dropDownOffsetHorizontal, mAutoCompleteTextView.getDropDownHorizontalOffset());
+ assertEquals(dropDownOffsetVertical, mAutoCompleteTextView.getDropDownVerticalOffset());
+ }
+
+ public void testDropDownBackground() {
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setAdapter(mAdapter));
+
+ mInstrumentation.runOnMainSync(() -> {
+ mAutoCompleteTextView.setDropDownBackgroundResource(R.drawable.blue_fill);
+ mAutoCompleteTextView.showDropDown();
+ });
+ mInstrumentation.waitForIdleSync();
+
+ Drawable dropDownBackground = mAutoCompleteTextView.getDropDownBackground();
+ TestUtils.assertAllPixelsOfColor("Drop down should be blue", dropDownBackground,
+ dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(),
+ false, Color.BLUE, 1, true);
+
+ mInstrumentation.runOnMainSync(() -> {
+ mAutoCompleteTextView.dismissDropDown();
+ mAutoCompleteTextView.setDropDownBackgroundDrawable(
+ mActivity.getDrawable(R.drawable.yellow_fill));
+ mAutoCompleteTextView.showDropDown();
+ });
+ mInstrumentation.waitForIdleSync();
+
+ dropDownBackground = mAutoCompleteTextView.getDropDownBackground();
+ TestUtils.assertAllPixelsOfColor("Drop down should be yellow", dropDownBackground,
+ dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(),
+ false, Color.YELLOW, 1, true);
}
@UiThreadTest
public void testReplaceText() {
MockAutoCompleteTextView autoCompleteTextView = new MockAutoCompleteTextView(mActivity);
+ final TextWatcher mockTextWatcher = mock(TextWatcher.class);
+ autoCompleteTextView.addTextChangedListener(mockTextWatcher);
+ verify(mockTextWatcher, never()).onTextChanged(any(CharSequence.class),
+ anyInt(), anyInt(), anyInt());
- assertEquals("", autoCompleteTextView.getText().toString());
- assertFalse(autoCompleteTextView.isOnTextChanged());
autoCompleteTextView.replaceText("Text");
assertEquals("Text", autoCompleteTextView.getText().toString());
- assertTrue(autoCompleteTextView.isOnTextChanged());
+ verify(mockTextWatcher, times(1)).onTextChanged(TestUtils.sameCharSequence("Text"),
+ eq(0), eq(0), eq("Text".length()));
- autoCompleteTextView.resetStatus();
- assertFalse(autoCompleteTextView.isOnTextChanged());
autoCompleteTextView.replaceText("Another");
assertEquals("Another", autoCompleteTextView.getText().toString());
- assertTrue(autoCompleteTextView.isOnTextChanged());
+ verify(mockTextWatcher, times(1)).onTextChanged(TestUtils.sameCharSequence("Another"),
+ eq(0), eq("Text".length()), eq("Another".length()));
}
@UiThreadTest
@@ -342,21 +434,17 @@
}
public void testGetThreshold() {
- final AutoCompleteTextView autoCompleteTextView = (AutoCompleteTextView) mActivity
- .findViewById(R.id.autocompletetv_edit);
- assertNotNull(autoCompleteTextView);
-
- assertEquals(1, autoCompleteTextView.getThreshold());
- autoCompleteTextView.setThreshold(3);
- assertEquals(3, autoCompleteTextView.getThreshold());
+ assertEquals(1, mAutoCompleteTextView.getThreshold());
+ mAutoCompleteTextView.setThreshold(3);
+ assertEquals(3, mAutoCompleteTextView.getThreshold());
// Test negative value input
- autoCompleteTextView.setThreshold(-5);
- assertEquals(1, autoCompleteTextView.getThreshold());
+ mAutoCompleteTextView.setThreshold(-5);
+ assertEquals(1, mAutoCompleteTextView.getThreshold());
// Test zero
- autoCompleteTextView.setThreshold(0);
- assertEquals(1, autoCompleteTextView.getThreshold());
+ mAutoCompleteTextView.setThreshold(0);
+ assertEquals(1, mAutoCompleteTextView.getThreshold());
}
public void testAccessValidater() {
@@ -371,7 +459,7 @@
assertNull(mAutoCompleteTextView.getValidator());
}
- public void testOnFilterComplete() throws Throwable {
+ public void testOnFilterComplete() {
// Set Threshold to 4 characters
mAutoCompleteTextView.setThreshold(4);
@@ -384,22 +472,15 @@
}
// Test the filter if the input string is not long enough to threshold
- runTestOnUiThread(new Runnable() {
- public void run() {
+ mInstrumentation.runOnMainSync(() -> {
mAutoCompleteTextView.setAdapter(mAdapter);
mAutoCompleteTextView.setText("");
mAutoCompleteTextView.requestFocus();
- }
});
mInstrumentation.sendStringSync(testString);
// onFilterComplete will close the popup.
- new PollingCheck() {
- @Override
- protected boolean check() {
- return !mAutoCompleteTextView.isPopupShowing();
- }
- }.run();
+ PollingCheck.waitFor(() -> !mAutoCompleteTextView.isPopupShowing());
if (mNumeric) {
// "that" in case of 12-key(NUMERIC) keyboard
@@ -408,20 +489,13 @@
testString = "that";
}
mInstrumentation.sendStringSync(testString);
- new PollingCheck() {
- @Override
- protected boolean check() {
- return !mAutoCompleteTextView.isPopupShowing();
- }
- }.run();
+ PollingCheck.waitFor(() -> !mAutoCompleteTextView.isPopupShowing());
// Test the expected filter matching scene
- runTestOnUiThread(new Runnable() {
- public void run() {
+ mInstrumentation.runOnMainSync(() -> {
mAutoCompleteTextView.setFocusable(true);
mAutoCompleteTextView.requestFocus();
mAutoCompleteTextView.setText("");
- }
});
if (mNumeric) {
// "test" in case of 12-key(NUMERIC) keyboard
@@ -431,20 +505,14 @@
}
assertTrue(mAutoCompleteTextView.hasFocus());
assertTrue(mAutoCompleteTextView.hasWindowFocus());
- new PollingCheck() {
- @Override
- protected boolean check() {
- return mAutoCompleteTextView.isPopupShowing();
- }
- }.run();
+ PollingCheck.waitFor(() -> mAutoCompleteTextView.isPopupShowing());
}
- public void testPerformFiltering() throws Throwable {
+ public void testPerformFiltering() {
if (isTvMode()) {
return;
}
- runTestOnUiThread(new Runnable() {
- public void run() {
+ mInstrumentation.runOnMainSync(() -> {
mAutoCompleteTextView.setAdapter(mAdapter);
mAutoCompleteTextView.setValidator(mValidator);
@@ -452,7 +520,6 @@
mAutoCompleteTextView.setFocusable(true);
mAutoCompleteTextView.requestFocus();
mAutoCompleteTextView.showDropDown();
- }
});
mInstrumentation.waitForIdleSync();
assertTrue(mAutoCompleteTextView.isPopupShowing());
@@ -461,11 +528,9 @@
// KeyBack will close the popup.
assertFalse(mAutoCompleteTextView.isPopupShowing());
- runTestOnUiThread(new Runnable() {
- public void run() {
+ mInstrumentation.runOnMainSync(() -> {
mAutoCompleteTextView.dismissDropDown();
mAutoCompleteTextView.setText(STRING_TEST);
- }
});
mInstrumentation.waitForIdleSync();
@@ -478,12 +543,10 @@
android.R.layout.simple_dropdown_item_1line, WORDS);
// Set Threshold to 4 charactersonKeyDown
- runTestOnUiThread(new Runnable() {
- public void run() {
+ mInstrumentation.runOnMainSync(() -> {
mAutoCompleteTextView.setAdapter(adapter);
mAutoCompleteTextView.requestFocus();
mAutoCompleteTextView.setText("");
- }
});
mInstrumentation.waitForIdleSync();
// Create and get the filter.
@@ -495,38 +558,27 @@
if (mNumeric) {
// "numeric" in case of 12-key(NUMERIC) keyboard
mInstrumentation.sendStringSync("6688633777444222");
- new PollingCheck() {
- @Override
- protected boolean check() {
- return "numeric".equals(filter.getResult());
- }
- }.run();
+ PollingCheck.waitFor(() -> "numeric".equals(filter.getResult()));
} else {
- Thread.sleep(200);
+ SystemClock.sleep(200);
mInstrumentation.sendStringSync(STRING_TEST);
- new PollingCheck() {
- @Override
- protected boolean check() {
- return STRING_TEST.equals(filter.getResult());
- }
- }.run();
+ PollingCheck.waitFor(() -> STRING_TEST.equals(filter.getResult()));
}
}
- public void testPerformCompletion() throws Throwable {
+ public void testPerformCompletionWithDPad() {
if (isTvMode()) {
return;
}
- final MockOnItemClickListener listener = new MockOnItemClickListener();
+ final AdapterView.OnItemClickListener mockItemClickListener =
+ mock(AdapterView.OnItemClickListener.class);
assertFalse(mAutoCompleteTextView.isPerformingCompletion());
- runTestOnUiThread(new Runnable() {
- public void run() {
- mAutoCompleteTextView.setOnItemClickListener(listener);
- mAutoCompleteTextView.setAdapter(mAdapter);
- mAutoCompleteTextView.requestFocus();
- mAutoCompleteTextView.showDropDown();
- }
+ mInstrumentation.runOnMainSync(() -> {
+ mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
+ mAutoCompleteTextView.setAdapter(mAdapter);
+ mAutoCompleteTextView.requestFocus();
+ mAutoCompleteTextView.showDropDown();
});
mInstrumentation.waitForIdleSync();
assertFalse(mAutoCompleteTextView.isPerformingCompletion());
@@ -535,54 +587,112 @@
mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER);
mInstrumentation.waitForIdleSync();
- assertTrue(listener.isOnItemClicked());
-
+ verify(mockItemClickListener, times(1)).onItemClick(any(AdapterView.class), any(View.class),
+ eq(0), eq(0L));
assertEquals(WORDS[0], mAutoCompleteTextView.getText().toString());
- // re-set 'clicked' flag to false
- listener.clearItemClickedStatus();
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- mAutoCompleteTextView.showDropDown();
- }
- });
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.showDropDown());
mInstrumentation.waitForIdleSync();
mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
- assertTrue(listener.isOnItemClicked());
+ verify(mockItemClickListener, times(2)).onItemClick(any(AdapterView.class), any(View.class),
+ eq(0), eq(0L));
assertEquals(WORDS[0], mAutoCompleteTextView.getText().toString());
assertFalse(mAutoCompleteTextView.isPerformingCompletion());
- listener.clearItemClickedStatus();
- runTestOnUiThread(new Runnable() {
- public void run() {
- mAutoCompleteTextView.showDropDown();
- }
- });
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.showDropDown());
mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
// Test normal key code.
mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_0);
- assertFalse(listener.isOnItemClicked());
+ verifyNoMoreInteractions(mockItemClickListener);
assertNotSame("", mAutoCompleteTextView.getText().toString());
assertFalse(mAutoCompleteTextView.isPerformingCompletion());
- listener.clearItemClickedStatus();
-
// Test the method on the scene of popup is closed.
- runTestOnUiThread(new Runnable() {
- public void run() {
- mAutoCompleteTextView.dismissDropDown();
- }
- });
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.dismissDropDown());
mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER);
- assertFalse(listener.isOnItemClicked());
+ verifyNoMoreInteractions(mockItemClickListener);
assertNotSame("", mAutoCompleteTextView.getText().toString());
assertFalse(mAutoCompleteTextView.isPerformingCompletion());
}
+ public void testPerformCompletionExplicit() {
+ final AdapterView.OnItemClickListener mockItemClickListener =
+ mock(AdapterView.OnItemClickListener.class);
+ assertFalse(mAutoCompleteTextView.isPerformingCompletion());
+
+ // Create a custom watcher that checks isPerformingCompletion to return true
+ // in the "middle" of the performCompletion processing. We also spy on this watcher
+ // to make sure that its onTextChanged is invoked.
+ final TextWatcher myTextWatcher = new MyTextWatcher(WORDS[1]);
+ final TextWatcher spyTextWatcher = spy(myTextWatcher);
+ mAutoCompleteTextView.addTextChangedListener(spyTextWatcher);
+
+ mInstrumentation.runOnMainSync(() -> {
+ mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
+ mAutoCompleteTextView.setAdapter(mAdapter);
+ mAutoCompleteTextView.requestFocus();
+ mAutoCompleteTextView.showDropDown();
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertTrue(mAutoCompleteTextView.isPopupShowing());
+ assertFalse(mAutoCompleteTextView.isPerformingCompletion());
+
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
+ mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.performCompletion());
+ verify(mockItemClickListener, times(1)).onItemClick(any(AdapterView.class), any(View.class),
+ eq(1), eq(1L));
+ assertEquals(WORDS[1], mAutoCompleteTextView.getText().toString());
+ assertFalse(mAutoCompleteTextView.isPerformingCompletion());
+ assertFalse(mAutoCompleteTextView.isPopupShowing());
+
+ verify(spyTextWatcher, atLeastOnce()).onTextChanged(TestUtils.sameCharSequence(WORDS[1]),
+ eq(0), eq(0), eq(WORDS[1].length()));
+ verifyNoMoreInteractions(mockItemClickListener);
+ }
+
+ public void testSetTextWithCompletion() {
+ final AdapterView.OnItemClickListener mockItemClickListener =
+ mock(AdapterView.OnItemClickListener.class);
+
+ mInstrumentation.runOnMainSync(() -> {
+ mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
+ mAutoCompleteTextView.setAdapter(mAdapter);
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertFalse(mAutoCompleteTextView.isPopupShowing());
+
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setText("testO", true));
+ mInstrumentation.waitForIdleSync();
+
+ assertTrue(mAutoCompleteTextView.isPopupShowing());
+ verifyZeroInteractions(mockItemClickListener);
+ }
+
+ public void testSetTextWithNoCompletion() {
+ final AdapterView.OnItemClickListener mockItemClickListener =
+ mock(AdapterView.OnItemClickListener.class);
+
+ mInstrumentation.runOnMainSync(() -> {
+ mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
+ mAutoCompleteTextView.setAdapter(mAdapter);
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertFalse(mAutoCompleteTextView.isPopupShowing());
+
+ mInstrumentation.runOnMainSync(() -> mAutoCompleteTextView.setText("testO", false));
+ mInstrumentation.waitForIdleSync();
+
+ assertFalse(mAutoCompleteTextView.isPopupShowing());
+ verifyZeroInteractions(mockItemClickListener);
+ }
+
@UiThreadTest
public void testPerformValidation() {
final CharSequence text = "this";
@@ -596,41 +706,27 @@
mAutoCompleteTextView.setValidator(null);
}
- public void testSetCompletionHint() {
+ public void testAccessCompletionHint() {
mAutoCompleteTextView.setCompletionHint("TEST HINT");
+ assertEquals("TEST HINT", mAutoCompleteTextView.getCompletionHint());
+
+ mAutoCompleteTextView.setCompletionHint(null);
+ assertNull(mAutoCompleteTextView.getCompletionHint());
}
- public void testOnAttachedToWindow() {
- // implement details, do not test
- }
+ public void testAccessListSelection() {
+ final AdapterView.OnItemClickListener mockItemClickListener =
+ mock(AdapterView.OnItemClickListener.class);
- public void testOnCommitCompletion() {
- // implement details, do not test
- }
-
- public void testOnDetachedFromWindow() {
- // implement details, do not test
- }
-
- public void testOnKeyPreIme() {
- // implement details, do not test
- }
-
- public void testAccessListSelection() throws Throwable {
- final MockOnItemClickListener listener = new MockOnItemClickListener();
-
- runTestOnUiThread(new Runnable() {
- public void run() {
- mAutoCompleteTextView.setOnItemClickListener(listener);
+ mInstrumentation.runOnMainSync(() -> {
+ mAutoCompleteTextView.setOnItemClickListener(mockItemClickListener);
mAutoCompleteTextView.setAdapter(mAdapter);
mAutoCompleteTextView.requestFocus();
mAutoCompleteTextView.showDropDown();
- }
});
mInstrumentation.waitForIdleSync();
- runTestOnUiThread(new Runnable() {
- public void run() {
+ mInstrumentation.runOnMainSync(() -> {
mAutoCompleteTextView.setListSelection(1);
assertEquals(1, mAutoCompleteTextView.getListSelection());
@@ -639,7 +735,6 @@
mAutoCompleteTextView.clearListSelection();
assertEquals(2, mAutoCompleteTextView.getListSelection());
- }
});
mInstrumentation.waitForIdleSync();
}
@@ -660,75 +755,25 @@
assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, mAutoCompleteTextView.getDropDownWidth());
}
- private static class MockOnItemClickListener implements AdapterView.OnItemClickListener {
- private boolean mOnItemClickedFlag = false;
-
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- mOnItemClickedFlag = true;
- return;
- }
-
- public boolean isOnItemClicked() {
- return mOnItemClickedFlag;
- }
-
- public void clearItemClickedStatus() {
- mOnItemClickedFlag = false;
- }
- }
-
- private static class MockOnItemSelectedListener implements AdapterView.OnItemSelectedListener {
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- return;
- }
-
- public void onNothingSelected(AdapterView<?> parent) {
- return;
- }
- }
-
private class MockValidator implements AutoCompleteTextView.Validator {
public CharSequence fixText(CharSequence invalidText) {
return STRING_VALIDATED;
}
public boolean isValid(CharSequence text) {
- if (text == STRING_TEST) {
- return true;
- }
- return false;
+ return (text == STRING_TEST);
}
}
- private static class MockAutoCompleteTextView extends AutoCompleteTextView {
- private boolean mOnTextChangedFlag = false;
- private boolean mOnFilterCompleteFlag = false;
- private String lastChangeText = "";
- private int mStart = 0;
- private int mBefore = 0;
- private int mAfter = 0;
-
- public void resetStatus() {
- mOnTextChangedFlag = false;
- mOnFilterCompleteFlag = false;
- mStart = 0;
- mBefore = 0;
- mAfter = 0;
- }
-
+ protected static class MockAutoCompleteTextView extends AutoCompleteTextView {
public MockAutoCompleteTextView(Context context) {
super(context);
- resetStatus();
}
public MockAutoCompleteTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
- protected MockAutoCompleteTextView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
@Override
protected CharSequence convertSelectionToString(Object selectedItem) {
return super.convertSelectionToString(selectedItem);
@@ -745,16 +790,6 @@
}
@Override
- protected void onTextChanged(CharSequence text, int start, int before, int after) {
- super.onTextChanged(text, start, before, after);
- mOnTextChangedFlag = true;
- lastChangeText = text.toString();
- mStart = start;
- mBefore = before;
- mAfter = after;
- }
-
- @Override
protected void performFiltering(CharSequence text, int keyCode) {
super.performFiltering(text, keyCode);
}
@@ -768,36 +803,6 @@
protected boolean setFrame(int l, int t, int r, int b) {
return super.setFrame(l, t, r, b);
}
-
- @Override
- public void onFilterComplete(int count) {
- super.onFilterComplete(count);
- mOnFilterCompleteFlag = true;
- }
-
- protected boolean isOnTextChanged() {
- return mOnTextChangedFlag;
- }
-
- protected String getLastChangeText() {
- return lastChangeText;
- }
-
- protected boolean isOnFilterComplete() {
- return mOnFilterCompleteFlag;
- }
-
- protected int getStart() {
- return mStart;
- }
-
- protected int getBefore() {
- return mBefore;
- }
-
- protected int getAfter() {
- return mAfter;
- }
}
private static class MockFilter extends Filter {
diff --git a/tests/tests/widget/src/android/widget/cts/BaseAdapterTest.java b/tests/tests/widget/src/android/widget/cts/BaseAdapterTest.java
index 7659c1e0..5a9a1fa 100644
--- a/tests/tests/widget/src/android/widget/cts/BaseAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/BaseAdapterTest.java
@@ -22,6 +22,8 @@
import android.view.ViewGroup;
import android.widget.BaseAdapter;
+import static org.mockito.Mockito.*;
+
/**
* Test {@link BaseAdapter}.
*/
@@ -33,34 +35,34 @@
public void testDataSetObserver() {
BaseAdapter baseAdapter = new MockBaseAdapter();
- MockDataSetObserver dataSetObserver = new MockDataSetObserver();
+ DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
- assertFalse(dataSetObserver.hasCalledOnChanged());
+ verifyZeroInteractions(mockDataSetObserver);
baseAdapter.notifyDataSetChanged();
- assertFalse(dataSetObserver.hasCalledOnChanged());
+ verifyZeroInteractions(mockDataSetObserver);
- baseAdapter.registerDataSetObserver(dataSetObserver);
+ baseAdapter.registerDataSetObserver(mockDataSetObserver);
baseAdapter.notifyDataSetChanged();
- assertTrue(dataSetObserver.hasCalledOnChanged());
+ verify(mockDataSetObserver, times(1)).onChanged();
- dataSetObserver.reset();
- assertFalse(dataSetObserver.hasCalledOnChanged());
- baseAdapter.unregisterDataSetObserver(dataSetObserver);
+ reset(mockDataSetObserver);
+ verifyZeroInteractions(mockDataSetObserver);
+ baseAdapter.unregisterDataSetObserver(mockDataSetObserver);
baseAdapter.notifyDataSetChanged();
- assertFalse(dataSetObserver.hasCalledOnChanged());
+ verifyZeroInteractions(mockDataSetObserver);
}
public void testNotifyDataSetInvalidated() {
BaseAdapter baseAdapter = new MockBaseAdapter();
- MockDataSetObserver dataSetObserver = new MockDataSetObserver();
+ DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
- assertFalse(dataSetObserver.hasCalledOnInvalidated());
+ verifyZeroInteractions(mockDataSetObserver);
baseAdapter.notifyDataSetInvalidated();
- assertFalse(dataSetObserver.hasCalledOnInvalidated());
+ verifyZeroInteractions(mockDataSetObserver);
- baseAdapter.registerDataSetObserver(dataSetObserver);
+ baseAdapter.registerDataSetObserver(mockDataSetObserver);
baseAdapter.notifyDataSetInvalidated();
- assertTrue(dataSetObserver.hasCalledOnInvalidated());
+ verify(mockDataSetObserver, times(1)).onInvalidated();
}
public void testAreAllItemsEnabled() {
@@ -121,34 +123,4 @@
return null;
}
}
-
- private static class MockDataSetObserver extends DataSetObserver {
- private boolean mCalledOnChanged = false;
- private boolean mCalledOnInvalidated = false;
-
- @Override
- public void onChanged() {
- super.onChanged();
- mCalledOnChanged = true;
- }
-
- public boolean hasCalledOnChanged() {
- return mCalledOnChanged;
- }
-
- @Override
- public void onInvalidated() {
- super.onInvalidated();
- mCalledOnInvalidated = true;
- }
-
- public boolean hasCalledOnInvalidated() {
- return mCalledOnInvalidated;
- }
-
- public void reset() {
- mCalledOnChanged = false;
- mCalledOnInvalidated = false;
- }
- }
}
diff --git a/tests/tests/widget/src/android/widget/cts/BaseExpandableListAdapterTest.java b/tests/tests/widget/src/android/widget/cts/BaseExpandableListAdapterTest.java
index 1737cfd..ad29526 100644
--- a/tests/tests/widget/src/android/widget/cts/BaseExpandableListAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/BaseExpandableListAdapterTest.java
@@ -22,6 +22,8 @@
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
+import static org.mockito.Mockito.*;
+
/**
* Test {@link BaseExpandableListAdapter}.
*/
@@ -54,22 +56,22 @@
public void testNotifyDataSetChanged() {
MockBaseExpandableListAdapter adapter = new MockBaseExpandableListAdapter();
- MockDataSetObserver dataSetObserver = new MockDataSetObserver();
- adapter.registerDataSetObserver(dataSetObserver);
+ DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
+ adapter.registerDataSetObserver(mockDataSetObserver);
- assertFalse(dataSetObserver.hasCalledOnChanged());
+ verifyZeroInteractions(mockDataSetObserver);
adapter.notifyDataSetChanged();
- assertTrue(dataSetObserver.hasCalledOnChanged());
+ verify(mockDataSetObserver, times(1)).onChanged();
}
public void testNotifyDataSetInvalidated() {
MockBaseExpandableListAdapter adapter = new MockBaseExpandableListAdapter();
- MockDataSetObserver dataSetObserver = new MockDataSetObserver();
- adapter.registerDataSetObserver(dataSetObserver);
+ DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
+ adapter.registerDataSetObserver(mockDataSetObserver);
- assertFalse(dataSetObserver.hasCalledOnInvalidated());
+ verifyZeroInteractions(mockDataSetObserver);
adapter.notifyDataSetInvalidated();
- assertTrue(dataSetObserver.hasCalledOnInvalidated());
+ verify(mockDataSetObserver, times(1)).onInvalidated();
}
public void testOnGroupCollapsed() {
@@ -86,47 +88,18 @@
public void testDataSetObserver() {
MockBaseExpandableListAdapter adapter = new MockBaseExpandableListAdapter();
- MockDataSetObserver dataSetObserver = new MockDataSetObserver();
- adapter.registerDataSetObserver(dataSetObserver);
+ DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
+ adapter.registerDataSetObserver(mockDataSetObserver);
- assertFalse(dataSetObserver.hasCalledOnChanged());
+ verifyZeroInteractions(mockDataSetObserver);
adapter.notifyDataSetChanged();
- assertTrue(dataSetObserver.hasCalledOnChanged());
+ verify(mockDataSetObserver, times(1)).onChanged();
- dataSetObserver.reset();
- assertFalse(dataSetObserver.hasCalledOnChanged());
- adapter.unregisterDataSetObserver(dataSetObserver);
+ reset(mockDataSetObserver);
+ verifyZeroInteractions(mockDataSetObserver);
+ adapter.unregisterDataSetObserver(mockDataSetObserver);
adapter.notifyDataSetChanged();
- assertFalse(dataSetObserver.hasCalledOnChanged());
- }
-
- private class MockDataSetObserver extends DataSetObserver {
- private boolean mCalledOnChanged = false;
- private boolean mCalledOnInvalidated = false;
-
- @Override
- public void onChanged() {
- super.onChanged();
- mCalledOnChanged = true;
- }
-
- public boolean hasCalledOnChanged() {
- return mCalledOnChanged;
- }
-
- @Override
- public void onInvalidated() {
- super.onInvalidated();
- mCalledOnInvalidated = true;
- }
-
- public boolean hasCalledOnInvalidated() {
- return mCalledOnInvalidated;
- }
-
- public void reset() {
- mCalledOnChanged = false;
- }
+ verifyZeroInteractions(mockDataSetObserver);
}
private class MockBaseExpandableListAdapter extends BaseExpandableListAdapter {
diff --git a/tests/tests/widget/src/android/widget/cts/CalendarViewTest.java b/tests/tests/widget/src/android/widget/cts/CalendarViewTest.java
index 31ad341..956ebf1 100644
--- a/tests/tests/widget/src/android/widget/cts/CalendarViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CalendarViewTest.java
@@ -18,14 +18,22 @@
import android.annotation.ColorInt;
import android.app.Instrumentation;
+import android.graphics.Rect;
+import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.MediumTest;
+import android.view.MotionEvent;
+import android.view.ViewGroup;
import android.widget.CalendarView;
+import android.widget.ScrollView;
import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
import java.util.Calendar;
import java.util.GregorianCalendar;
+import static org.mockito.Mockito.*;
+
@MediumTest
public class CalendarViewTest extends ActivityInstrumentationTestCase2<CalendarViewCtsActivity> {
private CalendarViewCtsActivity mActivity;
@@ -58,6 +66,13 @@
new CalendarView(mActivity, null, android.R.attr.calendarViewStyle);
+ new CalendarView(mActivity, null, 0, android.R.style.Widget_DeviceDefault_CalendarView);
+
+ new CalendarView(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_Light_CalendarView);
+
+ new CalendarView(mActivity, null, 0, android.R.style.Widget_Material_CalendarView);
+
new CalendarView(mActivity, null, 0, android.R.style.Widget_Material_Light_CalendarView);
}
@@ -103,6 +118,64 @@
assertEquals(mCalendarViewMaterial.getMaxDate(), maxDate);
}
+ private void verifyOnDateChangeListener(CalendarView calendarView,
+ boolean onlyAllowOneChangeEvent) {
+ final Instrumentation instrumentation = getInstrumentation();
+
+ final CalendarView.OnDateChangeListener mockDateChangeListener =
+ mock(CalendarView.OnDateChangeListener.class);
+ calendarView.setOnDateChangeListener(mockDateChangeListener);
+
+ // Go back to September 2008
+ final Calendar calendar = new GregorianCalendar();
+ calendar.set(Calendar.YEAR, 2008);
+ calendar.set(Calendar.MONTH, Calendar.SEPTEMBER);
+ calendar.set(Calendar.DAY_OF_MONTH, 16);
+ instrumentation.runOnMainSync(
+ () -> calendarView.setDate(calendar.getTime().getTime(), false, true));
+ instrumentation.waitForIdleSync();
+
+ // Get bounds of 09/23/2008
+ calendar.set(Calendar.DAY_OF_MONTH, 23);
+ final Rect dayBounds = new Rect();
+ final boolean getDayBoundsSuccess = calendarView.getBoundsForDate(
+ calendar.getTime().getTime(), dayBounds);
+ assertTrue(getDayBoundsSuccess);
+
+ if (onlyAllowOneChangeEvent) {
+ verifyZeroInteractions(mockDateChangeListener);
+ }
+
+ // Use instrumentation to emulate a tap on 09/23/2008
+ ViewTestUtils.emulateTapOnScreen(instrumentation, calendarView,
+ dayBounds.left + dayBounds.width() / 2,
+ dayBounds.top + dayBounds.height() / 2);
+
+ verify(mockDateChangeListener, times(1)).onSelectedDayChange(calendarView,
+ 2008, Calendar.SEPTEMBER, 23);
+ if (onlyAllowOneChangeEvent) {
+ verifyNoMoreInteractions(mockDateChangeListener);
+ }
+ }
+
+ public void testOnDateChangeListenerHolo() {
+ // Scroll the Holo calendar view all the way up so it's fully visible
+ final ScrollView scroller = (ScrollView) mActivity.findViewById(R.id.scroller);
+ final ViewGroup container = (ViewGroup) scroller.findViewById(R.id.container);
+ final Instrumentation instrumentation = getInstrumentation();
+
+ instrumentation.runOnMainSync(() -> scroller.scrollTo(0, container.getHeight()));
+ // Note that in pre-Material world we are "allowing" the CalendarView to notify
+ // the date change listener on multiple occasions. This is the old behavior of the widget.
+ verifyOnDateChangeListener(mCalendarViewHolo, false);
+ }
+
+ public void testOnDateChangeListenerMaterial() {
+ // Note that in Material world only "real" date change events are allowed to be reported
+ // to our listener. This is the new behavior of the widget.
+ verifyOnDateChangeListener(mCalendarViewMaterial, true);
+ }
+
public void testAppearanceMaterial() {
// The logic in this method is performed on a Material-styled CalendarView and
// non-deprecated attributes / visual appearance APIs
@@ -118,12 +191,12 @@
// Change the visual appearance of the widget
instrumentation.runOnMainSync(() -> {
- mCalendarViewMaterial.setFirstDayOfWeek(3);
+ mCalendarViewMaterial.setFirstDayOfWeek(Calendar.TUESDAY);
mCalendarViewMaterial.setDateTextAppearance(R.style.TextAppearance_WithColorBlue);
mCalendarViewMaterial.setWeekDayTextAppearance(R.style.TextAppearance_WithColorMagenta);
});
- assertEquals(3, mCalendarViewMaterial.getFirstDayOfWeek());
+ assertEquals(Calendar.TUESDAY, mCalendarViewMaterial.getFirstDayOfWeek());
assertEquals(R.style.TextAppearance_WithColorBlue,
mCalendarViewMaterial.getDateTextAppearance());
assertEquals(R.style.TextAppearance_WithColorMagenta,
@@ -166,7 +239,7 @@
mActivity.getColor(R.color.calendarview_week_separatorline_new);
instrumentation.runOnMainSync(() -> {
- mCalendarViewHolo.setFirstDayOfWeek(1);
+ mCalendarViewHolo.setFirstDayOfWeek(Calendar.SUNDAY);
mCalendarViewHolo.setShownWeekCount(4);
mCalendarViewHolo.setShowWeekNumber(true);
mCalendarViewHolo.setDateTextAppearance(R.style.TextAppearance_WithColorBlue);
@@ -178,7 +251,7 @@
mCalendarViewHolo.setWeekSeparatorLineColor(newWeekSeparatorLineColor);
});
- assertEquals(1, mCalendarViewHolo.getFirstDayOfWeek());
+ assertEquals(Calendar.SUNDAY, mCalendarViewHolo.getFirstDayOfWeek());
assertEquals(4, mCalendarViewHolo.getShownWeekCount());
assertTrue(mCalendarViewHolo.getShowWeekNumber());
assertEquals(R.style.TextAppearance_WithColorBlue,
diff --git a/tests/tests/widget/src/android/widget/cts/CheckBoxCtsActivity.java b/tests/tests/widget/src/android/widget/cts/CheckBoxCtsActivity.java
new file mode 100644
index 0000000..9ad0b23
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/CheckBoxCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.CheckBox;
+
+/**
+ * A minimal application for {@link CheckBox} test.
+ */
+public class CheckBoxCtsActivity extends Activity {
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.checkbox_layout);
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java b/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java
index b3a6e67..346861e 100644
--- a/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java
@@ -16,24 +16,47 @@
package android.widget.cts;
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.test.AndroidTestCase;
-import android.util.AttributeSet;
-import android.util.Xml;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
import android.widget.CheckBox;
+import android.widget.cts.util.ViewTestUtils;
-public class CheckBoxTest extends AndroidTestCase {
+import static org.mockito.Mockito.*;
+
+@SmallTest
+public class CheckBoxTest extends ActivityInstrumentationTestCase2<CheckBoxCtsActivity> {
+ private Instrumentation mInstrumentation;
+ private Activity mActivity;
+ private CheckBox mCheckBox;
+
+ public CheckBoxTest() {
+ super("android.widget.cts", CheckBoxCtsActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mInstrumentation = getInstrumentation();
+ mActivity = getActivity();
+ mCheckBox = (CheckBox) mActivity.findViewById(R.id.check_box);
+ }
+
public void testConstructor() {
- XmlPullParser parser = mContext.getResources().getXml(R.layout.checkbox_layout);
- AttributeSet mAttrSet = Xml.asAttributeSet(parser);
-
- new CheckBox(mContext, mAttrSet, 0);
- new CheckBox(mContext, mAttrSet);
- new CheckBox(mContext);
+ new CheckBox(mActivity);
+ new CheckBox(mActivity, null);
+ new CheckBox(mActivity, null, android.R.attr.checkboxStyle);
+ new CheckBox(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_CompoundButton_CheckBox);
+ new CheckBox(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_Light_CompoundButton_CheckBox);
+ new CheckBox(mActivity, null, 0,
+ android.R.style.Widget_Material_CompoundButton_CheckBox);
+ new CheckBox(mActivity, null, 0,
+ android.R.style.Widget_Material_Light_CompoundButton_CheckBox);
try {
new CheckBox(null, null, -1);
@@ -56,4 +79,109 @@
// expected, test success.
}
}
+
+ public void testText() {
+ assertTrue(TextUtils.equals(
+ mActivity.getString(R.string.hello_world), mCheckBox.getText()));
+
+ mInstrumentation.runOnMainSync(() -> mCheckBox.setText("new text"));
+ assertTrue(TextUtils.equals("new text", mCheckBox.getText()));
+
+ mInstrumentation.runOnMainSync(() -> mCheckBox.setText(R.string.text_name));
+ assertTrue(TextUtils.equals(mActivity.getString(R.string.text_name), mCheckBox.getText()));
+ }
+
+ public void testAccessChecked() {
+ final CheckBox.OnCheckedChangeListener mockCheckedChangeListener =
+ mock(CheckBox.OnCheckedChangeListener.class);
+ mCheckBox.setOnCheckedChangeListener(mockCheckedChangeListener);
+ verifyZeroInteractions(mockCheckedChangeListener);
+
+ assertFalse(mCheckBox.isChecked());
+
+ // not checked -> not checked
+ mInstrumentation.runOnMainSync(() -> mCheckBox.setChecked(false));
+ verifyZeroInteractions(mockCheckedChangeListener);
+ assertFalse(mCheckBox.isChecked());
+
+ // not checked -> checked
+ mInstrumentation.runOnMainSync(() -> mCheckBox.setChecked(true));
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, true);
+ assertTrue(mCheckBox.isChecked());
+
+ // checked -> checked
+ mInstrumentation.runOnMainSync(() -> mCheckBox.setChecked(true));
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, true);
+ assertTrue(mCheckBox.isChecked());
+
+ // checked -> not checked
+ mInstrumentation.runOnMainSync(() -> mCheckBox.setChecked(false));
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, false);
+ assertFalse(mCheckBox.isChecked());
+
+ verifyNoMoreInteractions(mockCheckedChangeListener);
+ }
+
+ public void testToggleViaApi() {
+ final CheckBox.OnCheckedChangeListener mockCheckedChangeListener =
+ mock(CheckBox.OnCheckedChangeListener.class);
+ mCheckBox.setOnCheckedChangeListener(mockCheckedChangeListener);
+ verifyZeroInteractions(mockCheckedChangeListener);
+
+ assertFalse(mCheckBox.isChecked());
+
+ // toggle to checked
+ mInstrumentation.runOnMainSync(() -> mCheckBox.toggle());
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, true);
+ assertTrue(mCheckBox.isChecked());
+
+ // toggle to not checked
+ mInstrumentation.runOnMainSync(() -> mCheckBox.toggle());
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, false);
+ assertFalse(mCheckBox.isChecked());
+
+ verifyNoMoreInteractions(mockCheckedChangeListener);
+ }
+
+ public void testToggleViaEmulatedTap() {
+ final CheckBox.OnCheckedChangeListener mockCheckedChangeListener =
+ mock(CheckBox.OnCheckedChangeListener.class);
+ mCheckBox.setOnCheckedChangeListener(mockCheckedChangeListener);
+ verifyZeroInteractions(mockCheckedChangeListener);
+
+ assertFalse(mCheckBox.isChecked());
+
+ // tap to checked
+ ViewTestUtils.emulateTapOnViewCenter(mInstrumentation, mCheckBox);
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, true);
+ assertTrue(mCheckBox.isChecked());
+
+ // tap to not checked
+ ViewTestUtils.emulateTapOnViewCenter(mInstrumentation, mCheckBox);
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, false);
+ assertFalse(mCheckBox.isChecked());
+
+ verifyNoMoreInteractions(mockCheckedChangeListener);
+ }
+
+ public void testToggleViaPerformClick() {
+ final CheckBox.OnCheckedChangeListener mockCheckedChangeListener =
+ mock(CheckBox.OnCheckedChangeListener.class);
+ mCheckBox.setOnCheckedChangeListener(mockCheckedChangeListener);
+ verifyZeroInteractions(mockCheckedChangeListener);
+
+ assertFalse(mCheckBox.isChecked());
+
+ // click to checked
+ mInstrumentation.runOnMainSync(() -> mCheckBox.performClick());
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, true);
+ assertTrue(mCheckBox.isChecked());
+
+ // click to not checked
+ mInstrumentation.runOnMainSync(() -> mCheckBox.performClick());
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCheckBox, false);
+ assertFalse(mCheckBox.isChecked());
+
+ verifyNoMoreInteractions(mockCheckedChangeListener);
+ }
}
diff --git a/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java
index 52bef54..066697a 100644
--- a/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java
@@ -16,13 +16,12 @@
package android.widget.cts;
-import android.widget.cts.R;
-
import android.app.Activity;
import android.os.Bundle;
+import android.widget.CheckedTextView;
/**
- * A minimal application for CheckedTextView test.
+ * A minimal application for {@link CheckedTextView} test.
*/
public class CheckedTextViewCtsActivity extends Activity {
/**
diff --git a/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java b/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java
index 039ca70..6c9350a 100644
--- a/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java
@@ -16,17 +16,17 @@
package android.widget.cts;
-import android.os.Parcelable;
-import android.widget.cts.R;
-
-
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
-import android.content.res.Resources;
+import android.content.res.ColorStateList;
import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
+import android.os.Parcelable;
import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
import android.util.AttributeSet;
import android.util.StateSet;
import android.view.View;
@@ -35,14 +35,19 @@
import android.widget.CheckedTextView;
import android.widget.ListAdapter;
import android.widget.ListView;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
import java.util.Arrays;
+@SmallTest
public class CheckedTextViewTest extends
ActivityInstrumentationTestCase2<CheckedTextViewCtsActivity> {
- private Resources mResources;
- private Activity mActivity;
private Instrumentation mInstrumentation;
+ private Activity mActivity;
+ private ListView mListView;
+ private CheckedTextView mCheckedTextView;
+ private Parcelable mState;
public CheckedTextViewTest() {
super("android.widget.cts", CheckedTextViewCtsActivity.class);
@@ -51,32 +56,42 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- mActivity = getActivity();
+
mInstrumentation = getInstrumentation();
- mResources = mActivity.getResources();
+ mActivity = getActivity();
+ mListView = (ListView) mActivity.findViewById(R.id.checkedtextview_listview);
+ mCheckedTextView = (CheckedTextView) mActivity.findViewById(R.id.checkedtextview_test);
}
public void testConstructor() {
- new MockCheckedTextView(mActivity, null, 0);
- new MockCheckedTextView(mActivity, null);
- new MockCheckedTextView(mActivity);
+ new CheckedTextView(mActivity);
+ new CheckedTextView(mActivity, null);
+ new CheckedTextView(mActivity, null, android.R.attr.checkedTextViewStyle);
+ new CheckedTextView(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_CheckedTextView);
+ new CheckedTextView(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_Light_CheckedTextView);
+ new CheckedTextView(mActivity, null, 0,
+ android.R.style.Widget_Material_CheckedTextView);
+ new CheckedTextView(mActivity, null, 0,
+ android.R.style.Widget_Material_Light_CheckedTextView);
try {
- new MockCheckedTextView(null, null, -1);
+ new CheckedTextView(null, null, -1);
fail("Should throw NullPointerException.");
} catch (NullPointerException e) {
// expected, test success.
}
try {
- new MockCheckedTextView(null, null);
+ new CheckedTextView(null, null);
fail("Should throw NullPointerException.");
} catch (NullPointerException e) {
// expected, test success.
}
try {
- new MockCheckedTextView(null);
+ new CheckedTextView(null);
fail("Should throw NullPointerException.");
} catch (NullPointerException e) {
// expected, test success.
@@ -84,35 +99,29 @@
}
public void testChecked() {
- final ListView lv = (ListView) mActivity.findViewById(R.id.checkedtextview_listview);
+ mInstrumentation.runOnMainSync(() -> {
+ mListView.setAdapter(new CheckedTextViewAdapter());
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- lv.setAdapter(new CheckedTextViewAdapter());
-
- lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
- lv.setItemChecked(1, true);
- }
+ mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ mListView.setItemChecked(1, true);
});
mInstrumentation.waitForIdleSync();
- assertEquals(1, lv.getCheckedItemPosition());
- assertTrue(lv.isItemChecked(1));
- assertFalse(lv.isItemChecked(0));
+ assertEquals(1, mListView.getCheckedItemPosition());
+ assertTrue(mListView.isItemChecked(1));
+ assertFalse(mListView.isItemChecked(0));
- ListAdapter adapter = lv.getAdapter();
- CheckedTextView view0 = (CheckedTextView) adapter.getView(0, null, null);
- CheckedTextView view1 = (CheckedTextView) adapter.getView(1, null, null);
- CheckedTextView view2 = (CheckedTextView) adapter.getView(2, null, null);
+ final ListAdapter adapter = mListView.getAdapter();
+ final CheckedTextView view0 = (CheckedTextView) adapter.getView(0, null, null);
+ final CheckedTextView view1 = (CheckedTextView) adapter.getView(1, null, null);
+ final CheckedTextView view2 = (CheckedTextView) adapter.getView(2, null, null);
assertFalse(view0.isChecked());
assertTrue(view1.isChecked());
assertFalse(view2.isChecked());
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
- lv.setItemChecked(2, true);
- }
+ mInstrumentation.runOnMainSync(() -> {
+ mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
+ mListView.setItemChecked(2, true);
});
mInstrumentation.waitForIdleSync();
assertFalse(view0.isChecked());
@@ -128,184 +137,219 @@
}
public void testToggle() {
- CheckedTextView checkedTextView = new MockCheckedTextView(mActivity);
- assertFalse(checkedTextView.isChecked());
+ assertFalse(mCheckedTextView.isChecked());
- checkedTextView.toggle();
- assertTrue(checkedTextView.isChecked());
+ mInstrumentation.runOnMainSync(() -> mCheckedTextView.toggle());
+ assertTrue(mCheckedTextView.isChecked());
- checkedTextView.toggle();
- assertFalse(checkedTextView.isChecked());
+ mInstrumentation.runOnMainSync(() -> mCheckedTextView.toggle());
+ assertFalse(mCheckedTextView.isChecked());
- checkedTextView.setChecked(true);
- checkedTextView.toggle();
- assertFalse(checkedTextView.isChecked());
+ mInstrumentation.runOnMainSync(() -> {
+ mCheckedTextView.setChecked(true);
+ mCheckedTextView.toggle();
+ });
+ assertFalse(mCheckedTextView.isChecked());
}
public void testDrawableStateChanged() {
MockCheckedTextView checkedTextView = new MockCheckedTextView(mActivity);
- checkedTextView.reset();
assertFalse(checkedTextView.hasDrawableStateChanged());
checkedTextView.refreshDrawableState();
assertTrue(checkedTextView.hasDrawableStateChanged());
}
public void testSetPadding() {
- final CheckedTextView lv
- = (CheckedTextView) mActivity.findViewById(R.id.checkedtextview_test);
- assertNotNull(lv);
-
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- lv.setPadding(1, 2, 3, 4);
- lv.requestLayout();
- }
+ mInstrumentation.runOnMainSync(() -> {
+ mListView.setPadding(1, 2, 3, 4);
+ mListView.requestLayout();
});
mInstrumentation.waitForIdleSync();
- int origTop = lv.getPaddingTop();
- int origBottom = lv.getPaddingBottom();
- int origLeft = lv.getPaddingLeft();
- int origRight = lv.getPaddingRight();
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- lv.setPadding(10, 20, 30, 40);
- lv.requestLayout();
- }
+ final int origTop = mListView.getPaddingTop();
+ final int origBottom = mListView.getPaddingBottom();
+ final int origLeft = mListView.getPaddingLeft();
+ final int origRight = mListView.getPaddingRight();
+
+ mInstrumentation.runOnMainSync(() -> {
+ mListView.setPadding(10, 20, 30, 40);
+ mListView.requestLayout();
});
mInstrumentation.waitForIdleSync();
- assertTrue(origTop < lv.getPaddingTop());
- assertTrue(origBottom < lv.getPaddingBottom());
- assertTrue(origLeft < lv.getPaddingLeft());
- assertTrue(origRight < lv.getPaddingRight());
+
+ assertTrue(origTop < mListView.getPaddingTop());
+ assertTrue(origBottom < mListView.getPaddingBottom());
+ assertTrue(origLeft < mListView.getPaddingLeft());
+ assertTrue(origRight < mListView.getPaddingRight());
}
private void cleanUpForceLayoutFlags(View view) {
if (view != null) {
- view.layout(0, 0, 0, 0);
+ mInstrumentation.runOnMainSync(() -> view.layout(0, 0, 0, 0));
assertFalse(view.isLayoutRequested());
}
}
public void testSetCheckMarkDrawableByDrawable() {
- CheckedTextView checkedTextView;
int basePaddingRight = 10;
// set drawable when checkedTextView is GONE
- checkedTextView = new MockCheckedTextView(mActivity);
- checkedTextView.setVisibility(View.GONE);
- Drawable firstDrawable = mResources.getDrawable(R.drawable.scenery);
+ mInstrumentation.runOnMainSync(() -> mCheckedTextView.setVisibility(View.GONE));
+ final Drawable firstDrawable = mActivity.getDrawable(R.drawable.scenery);
firstDrawable.setVisible(true, false);
assertEquals(StateSet.WILD_CARD, firstDrawable.getState());
- cleanUpForceLayoutFlags(checkedTextView);
+ cleanUpForceLayoutFlags(mCheckedTextView);
- checkedTextView.setCheckMarkDrawable(firstDrawable);
- assertEquals(firstDrawable.getIntrinsicWidth(), checkedTextView.getPaddingRight());
+ mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(firstDrawable));
+ assertEquals(firstDrawable.getIntrinsicWidth(), mCheckedTextView.getPaddingRight());
assertFalse(firstDrawable.isVisible());
- assertTrue(Arrays.equals(checkedTextView.getDrawableState(), firstDrawable.getState()));
- assertTrue(checkedTextView.isLayoutRequested());
+ assertTrue(Arrays.equals(mCheckedTextView.getDrawableState(), firstDrawable.getState()));
+ assertTrue(mCheckedTextView.isLayoutRequested());
+
+ mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(null));
// update drawable when checkedTextView is VISIBLE
- checkedTextView = new MockCheckedTextView(mActivity);
- checkedTextView.setVisibility(View.VISIBLE);
- checkedTextView.setPadding(0, 0, basePaddingRight, 0);
- Drawable secondDrawable = mResources.getDrawable(R.drawable.pass);
+ mInstrumentation.runOnMainSync(() -> {
+ mCheckedTextView.setVisibility(View.VISIBLE);
+ mCheckedTextView.setPadding(0, 0, basePaddingRight, 0);
+ });
+ final Drawable secondDrawable = mActivity.getDrawable(R.drawable.pass);
secondDrawable.setVisible(true, false);
assertEquals(StateSet.WILD_CARD, secondDrawable.getState());
- cleanUpForceLayoutFlags(checkedTextView);
+ cleanUpForceLayoutFlags(mCheckedTextView);
- checkedTextView.setCheckMarkDrawable(secondDrawable);
+ mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(secondDrawable));
assertEquals(secondDrawable.getIntrinsicWidth() + basePaddingRight,
- checkedTextView.getPaddingRight());
+ mCheckedTextView.getPaddingRight());
assertTrue(secondDrawable.isVisible());
- assertTrue(Arrays.equals(checkedTextView.getDrawableState(), secondDrawable.getState()));
- assertTrue(checkedTextView.isLayoutRequested());
+ assertTrue(Arrays.equals(mCheckedTextView.getDrawableState(), secondDrawable.getState()));
+ assertTrue(mCheckedTextView.isLayoutRequested());
- cleanUpForceLayoutFlags(checkedTextView);
- checkedTextView.setCheckMarkDrawable(null);
- assertEquals(basePaddingRight, checkedTextView.getPaddingRight());
- assertTrue(checkedTextView.isLayoutRequested());
+ cleanUpForceLayoutFlags(mCheckedTextView);
+ mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(null));
+ assertEquals(basePaddingRight, mCheckedTextView.getPaddingRight());
+ assertTrue(mCheckedTextView.isLayoutRequested());
}
public void testSetCheckMarkDrawableById() {
- CheckedTextView checkedTextView;
int basePaddingRight = 10;
// set drawable
- checkedTextView = new MockCheckedTextView(mActivity);
- checkedTextView.setPadding(0, 0, basePaddingRight, 0);
- Drawable firstDrawable = mResources.getDrawable(R.drawable.scenery);
- cleanUpForceLayoutFlags(checkedTextView);
+ mInstrumentation.runOnMainSync(
+ () -> mCheckedTextView.setPadding(0, 0, basePaddingRight, 0));
+ Drawable firstDrawable = mActivity.getDrawable(R.drawable.scenery);
+ cleanUpForceLayoutFlags(mCheckedTextView);
- checkedTextView.setCheckMarkDrawable(R.drawable.scenery);
+ mInstrumentation.runOnMainSync(
+ () -> mCheckedTextView.setCheckMarkDrawable(R.drawable.scenery));
assertEquals(firstDrawable.getIntrinsicWidth() + basePaddingRight,
- checkedTextView.getPaddingRight());
- assertTrue(checkedTextView.isLayoutRequested());
+ mCheckedTextView.getPaddingRight());
+ assertTrue(mCheckedTextView.isLayoutRequested());
// set the same drawable again
- cleanUpForceLayoutFlags(checkedTextView);
- checkedTextView.setCheckMarkDrawable(R.drawable.scenery);
+ cleanUpForceLayoutFlags(mCheckedTextView);
+ mInstrumentation.runOnMainSync(
+ () -> mCheckedTextView.setCheckMarkDrawable(R.drawable.scenery));
assertEquals(firstDrawable.getIntrinsicWidth() + basePaddingRight,
- checkedTextView.getPaddingRight());
- assertFalse(checkedTextView.isLayoutRequested());
+ mCheckedTextView.getPaddingRight());
+ assertFalse(mCheckedTextView.isLayoutRequested());
// update drawable
- Drawable secondDrawable = mResources.getDrawable(R.drawable.pass);
- checkedTextView.setCheckMarkDrawable(secondDrawable);
+ final Drawable secondDrawable = mActivity.getDrawable(R.drawable.pass);
+ mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(secondDrawable));
assertEquals(secondDrawable.getIntrinsicWidth() + basePaddingRight,
- checkedTextView.getPaddingRight());
- assertTrue(checkedTextView.isLayoutRequested());
+ mCheckedTextView.getPaddingRight());
+ assertTrue(mCheckedTextView.isLayoutRequested());
+
+ mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(null));
// resId is 0
- checkedTextView = new MockCheckedTextView(mActivity);
- checkedTextView.setPadding(0, 0, basePaddingRight, 0);
- cleanUpForceLayoutFlags(checkedTextView);
+ mInstrumentation.runOnMainSync(
+ () -> mCheckedTextView.setPadding(0, 0, basePaddingRight, 0));
+ cleanUpForceLayoutFlags(mCheckedTextView);
- checkedTextView.setCheckMarkDrawable(0);
- assertEquals(basePaddingRight, checkedTextView.getPaddingRight());
- assertFalse(checkedTextView.isLayoutRequested());
+ mInstrumentation.runOnMainSync(() -> mCheckedTextView.setCheckMarkDrawable(0));
+ assertEquals(basePaddingRight, mCheckedTextView.getPaddingRight());
+ assertFalse(mCheckedTextView.isLayoutRequested());
}
public void testSetCheckMarkByMixedTypes() {
- CheckedTextView checkedTextView = new MockCheckedTextView(mActivity);
- cleanUpForceLayoutFlags(checkedTextView);
+ cleanUpForceLayoutFlags(mCheckedTextView);
// Specifically test for b/22626247 (AOSP issue 180455).
- checkedTextView.setCheckMarkDrawable(R.drawable.scenery);
- checkedTextView.setCheckMarkDrawable(null);
- checkedTextView.setCheckMarkDrawable(R.drawable.scenery);
- assertNotNull(checkedTextView.getCheckMarkDrawable());
+ mInstrumentation.runOnMainSync(() -> {
+ mCheckedTextView.setCheckMarkDrawable(R.drawable.scenery);
+ mCheckedTextView.setCheckMarkDrawable(null);
+ mCheckedTextView.setCheckMarkDrawable(R.drawable.scenery);
+ });
+ assertNotNull(mCheckedTextView.getCheckMarkDrawable());
}
public void testAccessInstanceState() {
- CheckedTextView checkedTextView = new MockCheckedTextView(mActivity);
- Parcelable state;
+ assertFalse(mCheckedTextView.isChecked());
+ assertFalse(mCheckedTextView.getFreezesText());
- assertFalse(checkedTextView.isChecked());
- assertFalse(checkedTextView.getFreezesText());
+ mInstrumentation.runOnMainSync(() -> mState = mCheckedTextView.onSaveInstanceState());
+ assertNotNull(mState);
+ assertFalse(mCheckedTextView.getFreezesText());
- state = checkedTextView.onSaveInstanceState();
- assertNotNull(state);
- assertFalse(checkedTextView.getFreezesText());
+ mInstrumentation.runOnMainSync(() -> mCheckedTextView.setChecked(true));
- checkedTextView.setChecked(true);
-
- checkedTextView.onRestoreInstanceState(state);
- assertFalse(checkedTextView.isChecked());
- assertTrue(checkedTextView.isLayoutRequested());
+ mInstrumentation.runOnMainSync(() -> mCheckedTextView.onRestoreInstanceState(mState));
+ assertFalse(mCheckedTextView.isChecked());
+ assertTrue(mCheckedTextView.isLayoutRequested());
}
- public void testOnDraw() {
- // Do not test. Implementation details.
- }
+ public void testCheckMarkTinting() {
+ mInstrumentation.runOnMainSync(() -> mCheckedTextView.setChecked(true));
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mCheckedTextView,
+ () -> mCheckedTextView.setCheckMarkDrawable(R.drawable.icon_red));
- public void testOnCreateDrawableState() {
- // Do not test. Implementation details.
+ Drawable checkMark = mCheckedTextView.getCheckMarkDrawable();
+ TestUtils.assertAllPixelsOfColor("Initial state is red", checkMark,
+ checkMark.getBounds().width(), checkMark.getBounds().height(), false,
+ Color.RED, 1, true);
+
+ // With SRC_IN we're expecting the translucent tint color to "take over" the
+ // original red checkmark.
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mCheckedTextView, () -> {
+ mCheckedTextView.setCheckMarkTintMode(PorterDuff.Mode.SRC_IN);
+ mCheckedTextView.setCheckMarkTintList(ColorStateList.valueOf(0x8000FF00));
+ });
+
+ assertEquals(PorterDuff.Mode.SRC_IN, mCheckedTextView.getCheckMarkTintMode());
+ assertEquals(0x8000FF00, mCheckedTextView.getCheckMarkTintList().getDefaultColor());
+ checkMark = mCheckedTextView.getCheckMarkDrawable();
+ TestUtils.assertAllPixelsOfColor("Expected 50% green", checkMark,
+ checkMark.getIntrinsicWidth(), checkMark.getIntrinsicHeight(), false,
+ 0x8000FF00, 1, true);
+
+ // With SRC_OVER we're expecting the translucent tint color to be drawn on top
+ // of the original red checkmark, creating a composite color fill as the result.
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mCheckedTextView,
+ () -> mCheckedTextView.setCheckMarkTintMode(PorterDuff.Mode.SRC_OVER));
+
+ assertEquals(PorterDuff.Mode.SRC_OVER, mCheckedTextView.getCheckMarkTintMode());
+ assertEquals(0x8000FF00, mCheckedTextView.getCheckMarkTintList().getDefaultColor());
+ checkMark = mCheckedTextView.getCheckMarkDrawable();
+ TestUtils.assertAllPixelsOfColor("Expected 50% green over full red", checkMark,
+ checkMark.getIntrinsicWidth(), checkMark.getIntrinsicHeight(), false,
+ TestUtils.compositeColors(0x8000FF00, Color.RED), 1, true);
+
+ // Switch to a different color for the underlying checkmark and verify that the
+ // currently configured tinting (50% green overlay) is still respected
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mCheckedTextView,
+ () -> mCheckedTextView.setCheckMarkDrawable(R.drawable.icon_yellow));
+ assertEquals(PorterDuff.Mode.SRC_OVER, mCheckedTextView.getCheckMarkTintMode());
+ assertEquals(0x8000FF00, mCheckedTextView.getCheckMarkTintList().getDefaultColor());
+ checkMark = mCheckedTextView.getCheckMarkDrawable();
+ TestUtils.assertAllPixelsOfColor("Expected 50% green over full yellow", checkMark,
+ checkMark.getIntrinsicWidth(), checkMark.getIntrinsicHeight(), false,
+ TestUtils.compositeColors(0x8000FF00, Color.YELLOW), 1, true);
}
private static final class MockCheckedTextView extends CheckedTextView {
- private boolean mHasRefreshDrawableState = false;
private boolean mHasDrawableStateChanged = false;
public MockCheckedTextView(Context context) {
@@ -320,10 +364,6 @@
super(context, attrs, defStyle);
}
- public static int[] getSuperViewStateSet() {
- return ENABLED_STATE_SET;
- }
-
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
@@ -340,24 +380,9 @@
super.onDraw(canvas);
}
- @Override
- public void refreshDrawableState() {
- mHasRefreshDrawableState = true;
- super.refreshDrawableState();
- }
-
- public boolean hasRefreshDrawableState() {
- return mHasRefreshDrawableState;
- }
-
public boolean hasDrawableStateChanged() {
return mHasDrawableStateChanged;
}
-
- public void reset() {
- mHasRefreshDrawableState = false;
- mHasDrawableStateChanged = false;
- }
}
private class CheckedTextViewAdapter extends BaseAdapter {
diff --git a/tests/tests/widget/src/android/widget/cts/ChronometerTest.java b/tests/tests/widget/src/android/widget/cts/ChronometerTest.java
index ff1435f..4a66e25 100644
--- a/tests/tests/widget/src/android/widget/cts/ChronometerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ChronometerTest.java
@@ -16,17 +16,29 @@
package android.widget.cts;
-
+import android.app.Instrumentation;
+import android.content.Context;
+import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.ContextThemeWrapper;
import android.widget.Chronometer;
-import android.widget.Chronometer.OnChronometerTickListener;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.Mockito.*;
/**
* Test {@link Chronometer}.
*/
public class ChronometerTest extends ActivityInstrumentationTestCase2<ChronometerCtsActivity> {
+ private Instrumentation mInstrumentation;
private ChronometerCtsActivity mActivity;
+
public ChronometerTest() {
super("android.widget.cts", ChronometerCtsActivity.class);
}
@@ -34,6 +46,8 @@
@Override
protected void setUp() throws Exception {
super.setUp();
+
+ mInstrumentation = getInstrumentation();
mActivity = getActivity();
}
@@ -47,6 +61,22 @@
}
@UiThreadTest
+ public void testConstructorFromAttr() {
+ final Context context = new ContextThemeWrapper(mActivity, R.style.ChronometerAwareTheme);
+ final Chronometer chronometer = new Chronometer(context, null, R.attr.chronometerStyle);
+ assertTrue(chronometer.isCountDown());
+ assertEquals(mActivity.getString(R.string.chronometer_format), chronometer.getFormat());
+ }
+
+ @UiThreadTest
+ public void testConstructorFromStyle() {
+ final Chronometer chronometer = new Chronometer(mActivity, null, 0,
+ R.style.ChronometerStyle);
+ assertTrue(chronometer.isCountDown());
+ assertEquals(mActivity.getString(R.string.chronometer_format), chronometer.getFormat());
+ }
+
+ @UiThreadTest
public void testAccessBase() {
Chronometer chronometer = mActivity.getChronometer();
CharSequence oldText = chronometer.getText();
@@ -89,79 +119,94 @@
assertTrue(text.endsWith("trail"));
}
- public void testFoo() {
- // Do not test these APIs. They are callbacks which:
- // 1. The callback machanism has been tested in super class
- // 2. The functionality is implmentation details, no need to test
- }
-
- public void testStartAndStop() throws Throwable {
+ public void testStartAndStop() {
final Chronometer chronometer = mActivity.getChronometer();
// we will check the text is really updated every 1000ms after start,
// so we need sleep a moment to wait wait this time. The sleep code shouldn't
// in the same thread with UI, that's why we use runOnMainSync here.
- runTestOnUiThread(new Runnable() {
- public void run() {
- // the text will update immediately when call start.
- CharSequence expected = chronometer.getText();
- chronometer.start();
- assertNotSame(expected, chronometer.getText());
- }
+ mInstrumentation.runOnMainSync(() -> {
+ // the text will update immediately when call start.
+ final CharSequence valueBeforeStart = chronometer.getText();
+ chronometer.start();
+ assertNotSame(valueBeforeStart, chronometer.getText());
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
+
CharSequence expected = chronometer.getText();
- Thread.sleep(1500);
+ SystemClock.sleep(1500);
assertFalse(expected.equals(chronometer.getText()));
// we will check the text is really NOT updated anymore every 1000ms after stop,
// so we need sleep a moment to wait wait this time. The sleep code shouldn't
// in the same thread with UI, that's why we use runOnMainSync here.
- runTestOnUiThread(new Runnable() {
- public void run() {
- // the text will never be updated when call stop.
- CharSequence expected = chronometer.getText();
- chronometer.stop();
- assertSame(expected, chronometer.getText());
- }
+ mInstrumentation.runOnMainSync(() -> {
+ // the text will never be updated when call stop.
+ final CharSequence valueBeforeStop = chronometer.getText();
+ chronometer.stop();
+ assertSame(valueBeforeStop, chronometer.getText());
});
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
+
expected = chronometer.getText();
- Thread.sleep(1500);
+ SystemClock.sleep(1500);
assertTrue(expected.equals(chronometer.getText()));
}
- public void testAccessOnChronometerTickListener() throws Throwable {
+ public void testAccessOnChronometerTickListener() {
final Chronometer chronometer = mActivity.getChronometer();
- final MockOnChronometerTickListener listener = new MockOnChronometerTickListener();
+ final Chronometer.OnChronometerTickListener mockTickListener =
+ mock(Chronometer.OnChronometerTickListener.class);
- runTestOnUiThread(new Runnable() {
- public void run() {
- chronometer.setOnChronometerTickListener(listener);
- chronometer.start();
- }
+ mInstrumentation.runOnMainSync(() -> {
+ chronometer.setOnChronometerTickListener(mockTickListener);
+ chronometer.start();
});
- getInstrumentation().waitForIdleSync();
- assertEquals(listener, chronometer.getOnChronometerTickListener());
- assertTrue(listener.hasCalledOnChronometerTick());
- listener.reset();
- Thread.sleep(1500);
- assertTrue(listener.hasCalledOnChronometerTick());
+ mInstrumentation.waitForIdleSync();
+
+ assertEquals(mockTickListener, chronometer.getOnChronometerTickListener());
+ verify(mockTickListener, atLeastOnce()).onChronometerTick(chronometer);
+
+ reset(mockTickListener);
+ SystemClock.sleep(1500);
+ verify(mockTickListener, atLeastOnce()).onChronometerTick(chronometer);
}
- private static class MockOnChronometerTickListener implements OnChronometerTickListener {
- private boolean mCalledOnChronometerTick = false;
+ @LargeTest
+ public void testCountDown() {
+ final Chronometer chronometer = mActivity.getChronometer();
+ final Chronometer.OnChronometerTickListener mockTickListener =
+ mock(Chronometer.OnChronometerTickListener.class);
- public void onChronometerTick(Chronometer chronometer) {
- mCalledOnChronometerTick = true;
- }
+ mInstrumentation.runOnMainSync(() -> {
+ chronometer.setCountDown(true);
+ chronometer.setOnChronometerTickListener(mockTickListener);
+ chronometer.start();
+ });
+ mInstrumentation.waitForIdleSync();
- public boolean hasCalledOnChronometerTick() {
- return mCalledOnChronometerTick;
- }
+ assertTrue(chronometer.isCountDown());
- public void reset() {
- mCalledOnChronometerTick = false;
- }
+ SystemClock.sleep(5000);
+ verify(mockTickListener, atLeastOnce()).onChronometerTick(chronometer);
+ }
+
+ @LargeTest
+ public void testCountUp() {
+ final Chronometer chronometer = mActivity.getChronometer();
+ final Chronometer.OnChronometerTickListener mockTickListener =
+ mock(Chronometer.OnChronometerTickListener.class);
+
+ mInstrumentation.runOnMainSync(() -> {
+ chronometer.setCountDown(false);
+ chronometer.setOnChronometerTickListener(mockTickListener);
+ chronometer.start();
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertFalse(chronometer.isCountDown());
+
+ SystemClock.sleep(5000);
+ verify(mockTickListener, atLeastOnce()).onChronometerTick(chronometer);
}
}
diff --git a/tests/tests/widget/src/android/widget/cts/CompoundButtonTest.java b/tests/tests/widget/src/android/widget/cts/CompoundButtonTest.java
index 34d94a5..67d3fa8 100644
--- a/tests/tests/widget/src/android/widget/cts/CompoundButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CompoundButtonTest.java
@@ -16,21 +16,14 @@
package android.widget.cts;
-import android.content.res.ColorStateList;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.PorterDuff;
-import android.view.LayoutInflater;
-import android.widget.ToggleButton;
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
import android.content.Context;
+import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Parcelable;
import android.test.AndroidTestCase;
@@ -38,10 +31,17 @@
import android.util.StateSet;
import android.util.Xml;
import android.view.Gravity;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CompoundButton;
-import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.ToggleButton;
+import android.widget.cts.util.TestUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
/**
* Test {@link CompoundButton}.
@@ -87,44 +87,42 @@
public void testAccessChecked() {
CompoundButton compoundButton = new MockCompoundButton(mContext);
- MockOnCheckedChangeListener listener = new MockOnCheckedChangeListener();
- compoundButton.setOnCheckedChangeListener(listener);
+ CompoundButton.OnCheckedChangeListener mockCheckedChangeListener =
+ mock(CompoundButton.OnCheckedChangeListener.class);
+ compoundButton.setOnCheckedChangeListener(mockCheckedChangeListener);
assertFalse(compoundButton.isChecked());
- assertFalse(listener.hasCalledCheckedChange());
+ verifyZeroInteractions(mockCheckedChangeListener);
compoundButton.setChecked(true);
assertTrue(compoundButton.isChecked());
- assertTrue(listener.hasCalledCheckedChange());
- assertSame(compoundButton, listener.getInputCompoundButton());
- assertTrue(listener.getInputChecked());
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(compoundButton, true);
- listener.reset();
+ reset(mockCheckedChangeListener);
compoundButton.setChecked(true);
assertTrue(compoundButton.isChecked());
- assertFalse(listener.hasCalledCheckedChange());
+ verifyZeroInteractions(mockCheckedChangeListener);
compoundButton.setChecked(false);
assertFalse(compoundButton.isChecked());
- assertTrue(listener.hasCalledCheckedChange());
- assertSame(compoundButton, listener.getInputCompoundButton());
- assertFalse(listener.getInputChecked());
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(compoundButton, false);
}
public void testSetOnCheckedChangeListener() {
CompoundButton compoundButton = new MockCompoundButton(mContext);
- MockOnCheckedChangeListener listener = new MockOnCheckedChangeListener();
- compoundButton.setOnCheckedChangeListener(listener);
+ CompoundButton.OnCheckedChangeListener mockCheckedChangeListener =
+ mock(CompoundButton.OnCheckedChangeListener.class);
+ compoundButton.setOnCheckedChangeListener(mockCheckedChangeListener);
assertFalse(compoundButton.isChecked());
- assertFalse(listener.hasCalledCheckedChange());
+ verifyZeroInteractions(mockCheckedChangeListener);
compoundButton.setChecked(true);
- assertTrue(listener.hasCalledCheckedChange());
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(compoundButton, true);
// set null
compoundButton.setOnCheckedChangeListener(null);
- listener.reset();
+ reset(mockCheckedChangeListener);
compoundButton.setChecked(false);
- assertFalse(listener.hasCalledCheckedChange());
+ verifyZeroInteractions(mockCheckedChangeListener);
}
public void testToggle() {
@@ -154,10 +152,7 @@
assertFalse(compoundButton.isChecked());
// performClick with OnClickListener will return true.
- compoundButton.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- }
- });
+ compoundButton.setOnClickListener((view) -> {});
assertTrue(compoundButton.performClick());
assertTrue(compoundButton.isChecked());
@@ -340,53 +335,22 @@
assertEquals("Button tint mode inflated correctly",
PorterDuff.Mode.SRC_OVER, inflatedView.getButtonTintMode());
- MockDrawable button = new MockDrawable();
+ Drawable mockDrawable = spy(new ColorDrawable(Color.GREEN));
CompoundButton view = new ToggleButton(mContext);
- view.setButtonDrawable(button);
- assertFalse("No button tint applied by default", button.hasCalledSetTint());
+ view.setButtonDrawable(mockDrawable);
+ // No button tint applied by default
+ verify(mockDrawable, never()).setTintList(any(ColorStateList.class));
view.setButtonTintList(ColorStateList.valueOf(Color.WHITE));
- assertTrue("Button tint applied when setButtonTintList() called after setButton()",
- button.hasCalledSetTint());
+ // Button tint applied when setButtonTintList() called after setButton()
+ verify(mockDrawable, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE));
- button.reset();
+ reset(mockDrawable);
view.setButtonDrawable(null);
- view.setButtonDrawable(button);
- assertTrue("Button tint applied when setButtonTintList() called before setButton()",
- button.hasCalledSetTint());
- }
-
- private static class MockDrawable extends Drawable {
- private boolean mCalledSetTint = false;
-
- @Override
- public void draw(Canvas canvas) {}
-
- @Override
- public void setAlpha(int alpha) {}
-
- @Override
- public void setColorFilter(ColorFilter cf) {}
-
- @Override
- public void setTintList(ColorStateList tint) {
- super.setTintList(tint);
- mCalledSetTint = true;
- }
-
- @Override
- public int getOpacity() {
- return 0;
- }
-
- public boolean hasCalledSetTint() {
- return mCalledSetTint;
- }
-
- public void reset() {
- mCalledSetTint = false;
- }
+ view.setButtonDrawable(mockDrawable);
+ // Button tint applied when setButtonTintList() called before setButton()
+ verify(mockDrawable, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE));
}
private final class MockCompoundButton extends CompoundButton {
@@ -422,34 +386,4 @@
return super.verifyDrawable(who);
}
}
-
- private final class MockOnCheckedChangeListener implements OnCheckedChangeListener {
- private boolean mHasCalledChecked;
- private CompoundButton mCompoundButton;
- private boolean mIsChecked;
-
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- mHasCalledChecked = true;
- mCompoundButton = buttonView;
- mIsChecked = isChecked;
- }
-
- public boolean getInputChecked() {
- return mIsChecked;
- }
-
- public CompoundButton getInputCompoundButton() {
- return mCompoundButton;
- }
-
- public boolean hasCalledCheckedChange() {
- return mHasCalledChecked;
- }
-
- public void reset() {
- mHasCalledChecked = false;
- mCompoundButton = null;
- mIsChecked = false;
- }
- }
}
diff --git a/tests/tests/widget/src/android/widget/cts/CursorTreeAdapterTest.java b/tests/tests/widget/src/android/widget/cts/CursorTreeAdapterTest.java
index 8ef414d..0df58ff 100644
--- a/tests/tests/widget/src/android/widget/cts/CursorTreeAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CursorTreeAdapterTest.java
@@ -34,6 +34,8 @@
import android.widget.cts.R;
+import static org.mockito.Mockito.*;
+
/**
* Test {@link CursorTreeAdapter}.
@@ -199,23 +201,23 @@
@UiThreadTest
public void testNotifyDataSetChangedBoolean() {
MockCursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
- MockDataSetObserver observer = new MockDataSetObserver();
- adapter.registerDataSetObserver(observer);
+ DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
+ adapter.registerDataSetObserver(mockDataSetObserver);
// mChildrenCursorHelpers is empty
- assertFalse(observer.hasCalledOnChanged());
+ verifyZeroInteractions(mockDataSetObserver);
adapter.notifyDataSetChanged(false);
- assertTrue(observer.hasCalledOnChanged());
+ verify(mockDataSetObserver, times(1)).onChanged();
// add group 0 into mChildrenCursorHelpers
adapter.getChild(0, 0);
// add group 1 into mChildrenCursorHelpers
adapter.getChild(1, 0);
- observer.reset();
- assertFalse(observer.hasCalledOnChanged());
+ reset(mockDataSetObserver);
+ verifyZeroInteractions(mockDataSetObserver);
adapter.notifyDataSetChanged(true);
- assertTrue(observer.hasCalledOnChanged());
+ verify(mockDataSetObserver, times(1)).onChanged();
adapter.reset();
adapter.getChild(0, 0);
assertTrue(adapter.hasAddedChild1IntoCache());
@@ -223,11 +225,11 @@
assertTrue(adapter.hasAddedChild2IntoCache());
// both group 0 and group 1 are in mChildrenCursorHelpers
- observer.reset();
- assertFalse(observer.hasCalledOnChanged());
+ reset(mockDataSetObserver);
+ verifyZeroInteractions(mockDataSetObserver);
// does not release cursors
adapter.notifyDataSetChanged(false);
- assertTrue(observer.hasCalledOnChanged());
+ verify(mockDataSetObserver, times(1)).onChanged();
adapter.reset();
adapter.getChild(0, 0);
assertFalse(adapter.hasAddedChild1IntoCache());
@@ -238,22 +240,22 @@
@UiThreadTest
public void testNotifyDataSetChanged() {
MockCursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
- MockDataSetObserver observer = new MockDataSetObserver();
- adapter.registerDataSetObserver(observer);
+ DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
+ adapter.registerDataSetObserver(mockDataSetObserver);
// mChildrenCursorHelpers is empty
- assertFalse(observer.hasCalledOnChanged());
+ verifyZeroInteractions(mockDataSetObserver);
adapter.notifyDataSetChanged();
- assertTrue(observer.hasCalledOnChanged());
+ verify(mockDataSetObserver, times(1)).onChanged();
// add group 0 into mChildrenCursorHelpers
adapter.getChild(0, 0);
// add group 1 into mChildrenCursorHelpers
adapter.getChild(1, 0);
- observer.reset();
- assertFalse(observer.hasCalledOnChanged());
+ reset(mockDataSetObserver);
+ verifyZeroInteractions(mockDataSetObserver);
adapter.notifyDataSetChanged();
- assertTrue(observer.hasCalledOnChanged());
+ verify(mockDataSetObserver, times(1)).onChanged();
adapter.reset();
adapter.getChild(0, 0);
assertTrue(adapter.hasAddedChild1IntoCache());
@@ -264,22 +266,22 @@
@UiThreadTest
public void testNotifyDataSetInvalidated() {
MockCursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
- MockDataSetObserver observer = new MockDataSetObserver();
- adapter.registerDataSetObserver(observer);
+ DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
+ adapter.registerDataSetObserver(mockDataSetObserver);
- assertFalse(observer.hasCalledOnInvalidated());
+ verifyZeroInteractions(mockDataSetObserver);
// mChildrenCursorHelpers is empty
adapter.notifyDataSetInvalidated();
- assertTrue(observer.hasCalledOnInvalidated());
+ verify(mockDataSetObserver, times(1)).onInvalidated();
// add group 0 into mChildrenCursorHelpers
adapter.getChild(0, 0);
// add group 1 into mChildrenCursorHelpers
adapter.getChild(1, 0);
- observer.reset();
- assertFalse(observer.hasCalledOnInvalidated());
+ reset(mockDataSetObserver);
+ verifyZeroInteractions(mockDataSetObserver);
adapter.notifyDataSetInvalidated();
- assertTrue(observer.hasCalledOnInvalidated());
+ verify(mockDataSetObserver, times(1)).onInvalidated();
adapter.reset();
adapter.getChild(0, 0);
assertTrue(adapter.hasAddedChild1IntoCache());
@@ -707,34 +709,4 @@
return null;
}
}
-
- private final class MockDataSetObserver extends DataSetObserver {
- private boolean mHasCalledOnChanged = false;
- private boolean mHasCalledOnInvalidated = false;
-
- @Override
- public void onChanged() {
- super.onChanged();
- mHasCalledOnChanged = true;
- }
-
- @Override
- public void onInvalidated() {
- super.onInvalidated();
- mHasCalledOnInvalidated = true;
- }
-
- public boolean hasCalledOnChanged() {
- return mHasCalledOnChanged;
- }
-
- public boolean hasCalledOnInvalidated() {
- return mHasCalledOnInvalidated;
- }
-
- public void reset() {
- mHasCalledOnChanged = false;
- mHasCalledOnInvalidated = false;
- }
- }
}
diff --git a/tests/tests/widget/src/android/widget/cts/DatePickerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/DatePickerCtsActivity.java
new file mode 100644
index 0000000..81e6e69
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/DatePickerCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.DatePicker;
+
+/**
+ * A minimal application for {@link DatePicker} test.
+ */
+public class DatePickerCtsActivity extends Activity {
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.datepicker_layout);
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/DatePickerDialogTest.java b/tests/tests/widget/src/android/widget/cts/DatePickerDialogTest.java
index 1477f73..c8e888d 100644
--- a/tests/tests/widget/src/android/widget/cts/DatePickerDialogTest.java
+++ b/tests/tests/widget/src/android/widget/cts/DatePickerDialogTest.java
@@ -77,14 +77,7 @@
assertFalse("Date picker still dismissed", d.isShowing());
}
- private MockDatePickerDialog createDatePickerDialog() {
- return new MockDatePickerDialog(mActivity, null, 1970, 1, 1);
- }
-
- private class MockDatePickerDialog extends DatePickerDialog {
- public MockDatePickerDialog(Context context, OnDateSetListener callBack,
- int year, int monthOfYear, int dayOfMonth) {
- super(context, callBack, year, monthOfYear, dayOfMonth);
- }
+ private DatePickerDialog createDatePickerDialog() {
+ return new DatePickerDialog(mActivity, null, 1970, 1, 1);
}
}
diff --git a/tests/tests/widget/src/android/widget/cts/DatePickerTest.java b/tests/tests/widget/src/android/widget/cts/DatePickerTest.java
index c48f684..097cbe2 100644
--- a/tests/tests/widget/src/android/widget/cts/DatePickerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/DatePickerTest.java
@@ -16,120 +16,258 @@
package android.widget.cts;
-import android.widget.cts.R;
-
+import android.app.Activity;
+import android.app.Instrumentation;
import android.content.Context;
-import android.content.res.XmlResourceParser;
import android.os.Parcelable;
-import android.test.InstrumentationTestCase;
+import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
-import android.util.AttributeSet;
+import android.test.suitebuilder.annotation.MediumTest;
import android.util.SparseArray;
-import android.util.Xml;
import android.view.View;
import android.widget.DatePicker;
-import android.widget.cts.util.XmlUtils;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+import static org.mockito.Mockito.*;
/**
* Test {@link DatePicker}.
*/
-public class DatePickerTest extends InstrumentationTestCase {
+@MediumTest
+public class DatePickerTest extends ActivityInstrumentationTestCase2<DatePickerCtsActivity> {
+ private Activity mActivity;
+ private DatePicker mDatePickerSpinnerMode;
+ private DatePicker mDatePickerCalendarMode;
- private Context mContext;
+ public DatePickerTest() {
+ super("android.widget.cts", DatePickerCtsActivity.class);
+ }
@Override
- public void setUp() {
- mContext = getInstrumentation().getTargetContext();
+ protected void setUp() throws Exception {
+ super.setUp();
+ mActivity = getActivity();
+ mDatePickerSpinnerMode = (DatePicker) mActivity.findViewById(R.id.date_picker_spinner_mode);
+ mDatePickerCalendarMode =
+ (DatePicker) mActivity.findViewById(R.id.date_picker_calendar_mode);
}
- @UiThreadTest
public void testConstructor() {
- new DatePicker(mContext);
+ new DatePicker(mActivity);
- new DatePicker(mContext, null);
+ new DatePicker(mActivity, null);
- new DatePicker(mContext, getAttributeSet(R.layout.datepicker_layout));
+ new DatePicker(mActivity, null, android.R.attr.datePickerStyle);
- new DatePicker(mContext, getAttributeSet(R.layout.datepicker_layout), 0);
+ new DatePicker(mActivity, null, 0, android.R.style.Widget_DeviceDefault_DatePicker);
- // Test constructor with null Context, in fact, previous two functions will finally invoke
- // this version.
- try {
- // Test with null Context
- new DatePicker(null, getAttributeSet(R.layout.datepicker_layout), 0);
- fail("should throw NullPointerException");
- } catch (Exception e) {
- }
+ new DatePicker(mActivity, null, 0, android.R.style.Widget_Material_DatePicker);
+
+ new DatePicker(mActivity, null, 0, android.R.style.Widget_Material_Light_DatePicker);
}
- @UiThreadTest
public void testSetEnabled() {
- MockDatePicker datePicker = createDatePicker();
+ final Instrumentation instrumentation = getInstrumentation();
- assertTrue(datePicker.isEnabled());
+ assertTrue(mDatePickerCalendarMode.isEnabled());
- datePicker.setEnabled(false);
- assertFalse(datePicker.isEnabled());
+ instrumentation.runOnMainSync(() -> mDatePickerCalendarMode.setEnabled(false));
+ assertFalse(mDatePickerCalendarMode.isEnabled());
- datePicker.setEnabled(true);
- assertTrue(datePicker.isEnabled());
+ instrumentation.runOnMainSync(() -> mDatePickerCalendarMode.setEnabled(true));
+ assertTrue(mDatePickerCalendarMode.isEnabled());
}
- @UiThreadTest
+ private void verifyInit(DatePicker datePicker) {
+ final Instrumentation instrumentation = getInstrumentation();
+ final DatePicker.OnDateChangedListener mockDateChangeListener =
+ mock(DatePicker.OnDateChangedListener.class);
+
+ instrumentation.runOnMainSync(
+ () -> datePicker.init(2000, 10, 15, mockDateChangeListener));
+ assertEquals(2000, datePicker.getYear());
+ assertEquals(10, datePicker.getMonth());
+ assertEquals(15, datePicker.getDayOfMonth());
+
+ verifyZeroInteractions(mockDateChangeListener);
+ }
+
public void testInit() {
- MockOnDateChangedListener onDateChangedListener = new MockOnDateChangedListener();
- DatePicker datePicker = createDatePicker();
+ verifyInit(mDatePickerSpinnerMode);
+ verifyInit(mDatePickerCalendarMode);
+ }
- /* The month display uses 1-12 but our internal state stores it
- * 0-11 so add one when setting the display.
- */
- datePicker.init(2000, 10, 15, onDateChangedListener);
+ private void verifyAccessDate(DatePicker datePicker) {
+ final Instrumentation instrumentation = getInstrumentation();
+ final DatePicker.OnDateChangedListener mockDateChangeListener =
+ mock(DatePicker.OnDateChangedListener.class);
+
+ instrumentation.runOnMainSync(() -> datePicker.init(2000, 10, 15, mockDateChangeListener));
assertEquals(2000, datePicker.getYear());
assertEquals(10, datePicker.getMonth());
assertEquals(15, datePicker.getDayOfMonth());
+ verify(mockDateChangeListener, never()).onDateChanged(any(DatePicker.class), anyInt(),
+ anyInt(), anyInt());
+
+ instrumentation.runOnMainSync(() -> datePicker.updateDate(1989, 9, 19));
+ assertEquals(1989, datePicker.getYear());
+ assertEquals(9, datePicker.getMonth());
+ assertEquals(19, datePicker.getDayOfMonth());
+ verify(mockDateChangeListener, times(1)).onDateChanged(datePicker, 1989, 9, 19);
+
+ verifyNoMoreInteractions(mockDateChangeListener);
}
- @UiThreadTest
public void testAccessDate() {
- DatePicker datePicker = createDatePicker();
+ verifyAccessDate(mDatePickerSpinnerMode);
+ verifyAccessDate(mDatePickerCalendarMode);
+ }
- /* The month display uses 1-12 but our internal state stores it
- * 0-11 so add one when setting the display.
- */
- MockOnDateChangedListener onDateChangedListener = new MockOnDateChangedListener();
- datePicker.init(2000, 10, 15, onDateChangedListener);
+ private void verifySetOnDateChangedListener(DatePicker datePicker) {
+ final Instrumentation instrumentation = getInstrumentation();
+ final DatePicker.OnDateChangedListener mockDateChangeListener1 =
+ mock(DatePicker.OnDateChangedListener.class);
+ final DatePicker.OnDateChangedListener mockDateChangeListener2 =
+ mock(DatePicker.OnDateChangedListener.class);
+
+ instrumentation.runOnMainSync(() -> datePicker.init(2000, 10, 15, mockDateChangeListener1));
+ instrumentation.runOnMainSync(() -> datePicker.updateDate(1989, 9, 19));
+ assertEquals(1989, datePicker.getYear());
+ assertEquals(9, datePicker.getMonth());
+ assertEquals(19, datePicker.getDayOfMonth());
+ verify(mockDateChangeListener1, times(1)).onDateChanged(datePicker, 1989, 9, 19);
+ verify(mockDateChangeListener2, times(0)).onDateChanged(datePicker, 1989, 9, 19);
+
+ instrumentation.runOnMainSync(() -> datePicker.setOnDateChangedListener(
+ mockDateChangeListener2));
+ instrumentation.runOnMainSync(() -> datePicker.updateDate(2000, 10, 15));
assertEquals(2000, datePicker.getYear());
assertEquals(10, datePicker.getMonth());
assertEquals(15, datePicker.getDayOfMonth());
+ verify(mockDateChangeListener1, times(0)).onDateChanged(datePicker, 2000, 10, 15);
+ verify(mockDateChangeListener2, times(1)).onDateChanged(datePicker, 2000, 10, 15);
- datePicker.updateDate(1989, 9, 19);
+ }
+
+ public void testSetOnDateChangedListener() {
+ verifySetOnDateChangedListener(mDatePickerSpinnerMode);
+ verifySetOnDateChangedListener(mDatePickerCalendarMode);
+ }
+
+ private void verifyUpdateDate(DatePicker datePicker) {
+ final Instrumentation instrumentation = getInstrumentation();
+
+ instrumentation.runOnMainSync(() -> datePicker.updateDate(1989, 9, 19));
assertEquals(1989, datePicker.getYear());
assertEquals(9, datePicker.getMonth());
assertEquals(19, datePicker.getDayOfMonth());
}
- @UiThreadTest
public void testUpdateDate() {
- DatePicker datePicker = createDatePicker();
+ verifyUpdateDate(mDatePickerSpinnerMode);
+ verifyUpdateDate(mDatePickerCalendarMode);
+ }
- // Test normal input values
- /* The month display uses 1-12 but our internal state stores it
- * 0-11 so add one when setting the display.
- */
- datePicker.updateDate(1989, 9, 19);
- assertEquals(1989, datePicker.getYear());
- assertEquals(9, datePicker.getMonth());
- assertEquals(19, datePicker.getDayOfMonth());
+ private void verifyMinMaxDate(DatePicker datePicker) {
+ final Instrumentation instrumentation = getInstrumentation();
+
+ // Use a range of minus/plus one year as min/max dates
+ final Calendar minCalendar = new GregorianCalendar();
+ minCalendar.set(Calendar.YEAR, minCalendar.get(Calendar.YEAR) - 1);
+ final Calendar maxCalendar = new GregorianCalendar();
+ maxCalendar.set(Calendar.YEAR, maxCalendar.get(Calendar.YEAR) + 1);
+
+ final long minDate = minCalendar.getTime().getTime();
+ final long maxDate = maxCalendar.getTime().getTime();
+
+ instrumentation.runOnMainSync(() -> {
+ datePicker.setMinDate(minDate);
+ datePicker.setMaxDate(maxDate);
+ });
+
+ assertEquals(datePicker.getMinDate(), minDate);
+ assertEquals(datePicker.getMaxDate(), maxDate);
+ }
+
+ public void testMinMaxDate() {
+ verifyMinMaxDate(mDatePickerSpinnerMode);
+ verifyMinMaxDate(mDatePickerCalendarMode);
+ }
+
+ private void verifyFirstDayOfWeek(DatePicker datePicker) {
+ final Instrumentation instrumentation = getInstrumentation();
+
+ instrumentation.runOnMainSync(() -> datePicker.setFirstDayOfWeek(Calendar.TUESDAY));
+ assertEquals(Calendar.TUESDAY, datePicker.getFirstDayOfWeek());
+
+ instrumentation.runOnMainSync(() -> datePicker.setFirstDayOfWeek(Calendar.SUNDAY));
+ assertEquals(Calendar.SUNDAY, datePicker.getFirstDayOfWeek());
+ }
+
+ public void testFirstDayOfWeek() {
+ verifyFirstDayOfWeek(mDatePickerSpinnerMode);
+ verifyFirstDayOfWeek(mDatePickerCalendarMode);
+ }
+
+ public void testCalendarViewInSpinnerMode() {
+ final Instrumentation instrumentation = getInstrumentation();
+
+ assertNotNull(mDatePickerSpinnerMode.getCalendarView());
+
+ // Update the DatePicker and test that its CalendarView is synced to the same date
+ final Calendar calendar = new GregorianCalendar();
+ calendar.set(Calendar.YEAR, 2008);
+ calendar.set(Calendar.MONTH, Calendar.SEPTEMBER);
+ calendar.set(Calendar.DAY_OF_MONTH, 23);
+ instrumentation.runOnMainSync(
+ () -> mDatePickerSpinnerMode.updateDate(
+ calendar.get(Calendar.YEAR),
+ calendar.get(Calendar.MONTH),
+ calendar.get(Calendar.DAY_OF_MONTH)));
+
+ final Calendar calendarFromSpinner = new GregorianCalendar();
+ final long timeFromSpinnerCalendar = mDatePickerSpinnerMode.getCalendarView().getDate();
+ calendarFromSpinner.setTimeInMillis(timeFromSpinnerCalendar);
+
+ assertEquals(calendar.get(Calendar.YEAR), calendarFromSpinner.get(Calendar.YEAR));
+ assertEquals(calendar.get(Calendar.MONTH), calendarFromSpinner.get(Calendar.MONTH));
+ assertEquals(calendar.get(Calendar.DAY_OF_MONTH),
+ calendarFromSpinner.get(Calendar.DAY_OF_MONTH));
+ }
+
+ public void testPartsVisibilityInSpinnerMode() {
+ final Instrumentation instrumentation = getInstrumentation();
+
+ assertTrue(mDatePickerSpinnerMode.getSpinnersShown());
+ assertTrue(mDatePickerSpinnerMode.getCalendarViewShown());
+
+ instrumentation.runOnMainSync(() -> mDatePickerSpinnerMode.setSpinnersShown(false));
+ assertFalse(mDatePickerSpinnerMode.getSpinnersShown());
+ assertTrue(mDatePickerSpinnerMode.getCalendarViewShown());
+
+ instrumentation.runOnMainSync(() -> mDatePickerSpinnerMode.setCalendarViewShown(false));
+ assertFalse(mDatePickerSpinnerMode.getSpinnersShown());
+ assertFalse(mDatePickerSpinnerMode.getCalendarViewShown());
+
+ instrumentation.runOnMainSync(() -> mDatePickerSpinnerMode.setSpinnersShown(true));
+ assertTrue(mDatePickerSpinnerMode.getSpinnersShown());
+ assertFalse(mDatePickerSpinnerMode.getCalendarViewShown());
+
+ instrumentation.runOnMainSync(() -> mDatePickerSpinnerMode.setCalendarViewShown(true));
+ assertTrue(mDatePickerSpinnerMode.getSpinnersShown());
+ assertTrue(mDatePickerSpinnerMode.getCalendarViewShown());
}
@UiThreadTest
- public void testOnSaveInstanceState() {
- MockDatePicker datePicker = createDatePicker();
+ public void testAccessInstanceState() {
+ MockDatePicker datePicker = new MockDatePicker(mActivity);
datePicker.updateDate(2008, 9, 10);
SparseArray<Parcelable> container = new SparseArray<Parcelable>();
- // Test onSaveHierarchyState
+ // Test saveHierarchyState -> onSaveInstanceState path
assertEquals(View.NO_ID, datePicker.getId());
datePicker.setId(99);
assertFalse(datePicker.hasCalledOnSaveInstanceState());
@@ -137,43 +275,23 @@
assertEquals(1, datePicker.getChildCount());
assertTrue(datePicker.hasCalledOnSaveInstanceState());
- // Test dispatchRestoreInstanceState
- datePicker = createDatePicker();
+ // Test dispatchRestoreInstanceState -> onRestoreInstanceState path
+ datePicker = new MockDatePicker(mActivity);
datePicker.setId(99);
assertFalse(datePicker.hasCalledOnRestoreInstanceState());
datePicker.dispatchRestoreInstanceState(container);
assertEquals(2008, datePicker.getYear());
assertEquals(9, datePicker.getMonth());
assertEquals(10, datePicker.getDayOfMonth());
-
- // Test onRestoreInstanceState
assertTrue(datePicker.hasCalledOnRestoreInstanceState());
}
- private AttributeSet getAttributeSet(int resourceId) {
- final XmlResourceParser parser = mContext.getResources().getXml(resourceId);
- try {
- XmlUtils.beginDocument(parser, "RelativeLayout");
- } catch (Exception e) {
- fail("Found unexpected loading process error before invoking generateLayoutParams.");
- }
- final AttributeSet attr = Xml.asAttributeSet(parser);
- assertNotNull(attr);
- return attr;
- }
-
- private MockDatePicker createDatePicker() {
- MockDatePicker datePicker = new MockDatePicker(mContext,
- getAttributeSet(R.layout.datepicker_layout));
- return datePicker;
- }
-
private class MockDatePicker extends DatePicker {
private boolean mCalledOnSaveInstanceState = false;
private boolean mCalledOnRestoreInstanceState = false;
- public MockDatePicker(Context context, AttributeSet attrs) {
- super(context, attrs);
+ public MockDatePicker(Context context) {
+ super(context);
}
@Override
@@ -201,10 +319,4 @@
return mCalledOnRestoreInstanceState;
}
}
-
- private class MockOnDateChangedListener implements DatePicker.OnDateChangedListener {
- public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
-
- }
- }
}
diff --git a/tests/tests/widget/src/android/widget/cts/DialerFilterTest.java b/tests/tests/widget/src/android/widget/cts/DialerFilterTest.java
index a99f56a..8616448 100644
--- a/tests/tests/widget/src/android/widget/cts/DialerFilterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/DialerFilterTest.java
@@ -53,12 +53,7 @@
super.setUp();
mActivity = getActivity();
- new PollingCheck() {
- @Override
- protected boolean check() {
- return mActivity.hasWindowFocus();
- }
- }.run();
+ PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
mInstrumentation = getInstrumentation();
mDialerFilter = (DialerFilter) mActivity.findViewById(R.id.dialer_filter);
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableList.java b/tests/tests/widget/src/android/widget/cts/ExpandableList.java
new file mode 100644
index 0000000..48fa5e9
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableList.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts;
+
+import android.widget.ExpandableListAdapter;
+
+public class ExpandableList extends ExpandableListBasic {
+ @Override
+ protected ExpandableListAdapter createAdapter() {
+ return null;
+ }
+
+ @Override
+ protected boolean shouldRegisterItemClickListener() {
+ return false;
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListSimple.java b/tests/tests/widget/src/android/widget/cts/ExpandableListBasic.java
similarity index 71%
rename from tests/tests/widget/src/android/widget/cts/ExpandableListSimple.java
rename to tests/tests/widget/src/android/widget/cts/ExpandableListBasic.java
index f2e87ee7..52bb0a06 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListSimple.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListBasic.java
@@ -22,22 +22,22 @@
import android.widget.BaseExpandableListAdapter;
import android.widget.cts.util.ExpandableListScenario;
-public class ExpandableListSimple extends ExpandableListScenario {
- private static final int[] NUM_CHILDREN = {4, 3, 2, 1, 0};
+public class ExpandableListBasic extends ExpandableListScenario {
+ private static final int[] CHILD_COUNT = {4, 3, 2, 1, 0};
@Override
protected void init(ExpandableParams params) {
- params.setNumChildren(NUM_CHILDREN).setItemScreenSizeFactor(0.14);
+ params.setNumChildren(CHILD_COUNT).setItemScreenSizeFactor(0.14);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- menu.add("Add item").setOnMenuItemClickListener(new OnMenuItemClickListener() {
- public boolean onMenuItemClick(MenuItem item) {
+ menu.add("Add item").setOnMenuItemClickListener((MenuItem item) -> {
mGroups.add(0, new MyGroup(2));
- ((BaseExpandableListAdapter) mAdapter).notifyDataSetChanged();
+ if (mAdapter != null) {
+ ((BaseExpandableListAdapter) mAdapter).notifyDataSetChanged();
+ }
return true;
- }
});
return true;
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListViewBasicTest.java b/tests/tests/widget/src/android/widget/cts/ExpandableListViewBasicTest.java
index dd8d6a2..b40a75f 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListViewBasicTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListViewBasicTest.java
@@ -16,7 +16,7 @@
package android.widget.cts;
-
+import android.app.Instrumentation;
import android.cts.util.PollingCheck;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.MediumTest;
@@ -30,34 +30,31 @@
import java.util.List;
+@MediumTest
public class ExpandableListViewBasicTest extends
- ActivityInstrumentationTestCase2<ExpandableListSimple> {
+ ActivityInstrumentationTestCase2<ExpandableListBasic> {
+ private Instrumentation mInstrumentation;
private ExpandableListScenario mActivity;
private ExpandableListView mExpandableListView;
private ExpandableListAdapter mAdapter;
private ListUtil mListUtil;
public ExpandableListViewBasicTest() {
- super(ExpandableListSimple.class);
+ super(ExpandableListBasic.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
+ mInstrumentation = getInstrumentation();
mActivity = getActivity();
- new PollingCheck() {
- @Override
- protected boolean check() {
- return mActivity.hasWindowFocus();
- }
- }.run();
+ PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
mExpandableListView = mActivity.getExpandableListView();
mAdapter = mExpandableListView.getExpandableListAdapter();
mListUtil = new ListUtil(mExpandableListView, getInstrumentation());
}
- @MediumTest
public void testPreconditions() {
assertNotNull(mActivity);
assertNotNull(mExpandableListView);
@@ -69,7 +66,7 @@
assertTrue("Could not find group to expand", groupPos >= 0);
assertFalse("Group is already expanded", mExpandableListView.isGroupExpanded(groupPos));
mListUtil.arrowScrollToSelectedPosition(groupPos);
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
getInstrumentation().waitForIdleSync();
assertTrue("Group did not expand", mExpandableListView.isGroupExpanded(groupPos));
@@ -77,32 +74,29 @@
return groupPos;
}
- @MediumTest
public void testExpandGroup() {
expandGroup(-1, true);
}
- @MediumTest
public void testCollapseGroup() {
final int groupPos = expandGroup(-1, true);
sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
assertFalse("Group did not collapse", mExpandableListView.isGroupExpanded(groupPos));
}
- @MediumTest
public void testExpandedGroupMovement() {
// Expand the first group
mListUtil.arrowScrollToSelectedPosition(0);
sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
// Ensure it expanded
assertTrue("Group did not expand", mExpandableListView.isGroupExpanded(0));
// Wait until that's all good
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.waitForIdleSync();
// Make sure it expanded
assertTrue("Group did not expand", mExpandableListView.isGroupExpanded(0));
@@ -117,12 +111,8 @@
mAdapter instanceof BaseExpandableListAdapter);
final BaseExpandableListAdapter adapter = (BaseExpandableListAdapter) mAdapter;
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- adapter.notifyDataSetChanged();
- }
- });
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> adapter.notifyDataSetChanged());
+ mInstrumentation.waitForIdleSync();
// Make sure the right group is expanded
assertTrue("The expanded state didn't stay with the proper group",
@@ -131,20 +121,17 @@
mExpandableListView.isGroupExpanded(0));
}
- @MediumTest
public void testContextMenus() {
ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
tester.testContextMenus();
}
- @MediumTest
public void testConvertionBetweenFlatAndPacked() {
ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
tester.testConvertionBetweenFlatAndPackedOnGroups();
tester.testConvertionBetweenFlatAndPackedOnChildren();
}
- @MediumTest
public void testSelectedPosition() {
ExpandableListTester tester = new ExpandableListTester(mExpandableListView, this);
tester.testSelectedPositionOnGroups();
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java b/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
index e773ebf..b6b238e 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
@@ -16,43 +16,76 @@
package android.widget.cts;
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
+import android.app.Instrumentation;
import android.content.Context;
+import android.cts.util.PollingCheck;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Parcelable;
-import android.test.AndroidTestCase;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
import android.util.AttributeSet;
import android.util.Xml;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.AdapterView;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ListAdapter;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.ExpandableListView.OnChildClickListener;
-import android.widget.ExpandableListView.OnGroupClickListener;
+import android.widget.TextView;
+import android.widget.cts.util.ExpandableListScenario;
-public class ExpandableListViewTest extends AndroidTestCase {
+import org.xmlpull.v1.XmlPullParser;
+
+import static org.mockito.Mockito.*;
+
+@MediumTest
+public class ExpandableListViewTest extends ActivityInstrumentationTestCase2<ExpandableList> {
+ private Instrumentation mInstrumentation;
+ private ExpandableListScenario mActivity;
+ private ExpandableListView mExpandableListView;
+
+ public ExpandableListViewTest() {
+ super(ExpandableList.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mInstrumentation = getInstrumentation();
+ mActivity = getActivity();
+ PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
+ mExpandableListView = mActivity.getExpandableListView();
+ }
+
public void testConstructor() {
- new ExpandableListView(mContext);
+ new ExpandableListView(mActivity);
- new ExpandableListView(mContext, null);
+ new ExpandableListView(mActivity, null);
- new ExpandableListView(mContext, null, 0);
+ new ExpandableListView(mActivity, null, android.R.attr.expandableListViewStyle);
+
+ new ExpandableListView(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_ExpandableListView);
+
+ new ExpandableListView(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_Light_ExpandableListView);
+
+ new ExpandableListView(mActivity, null, 0,
+ android.R.style.Widget_Material_ExpandableListView);
+
+ new ExpandableListView(mActivity, null, 0,
+ android.R.style.Widget_Material_Light_ExpandableListView);
XmlPullParser parser =
- getContext().getResources().getXml(R.layout.expandablelistview_layout);
+ mActivity.getResources().getXml(R.layout.expandablelistview_layout);
AttributeSet attrs = Xml.asAttributeSet(parser);
- new ExpandableListView(mContext, attrs);
- new ExpandableListView(mContext, attrs, 0);
+ new ExpandableListView(mActivity, attrs);
+ new ExpandableListView(mActivity, attrs, 0);
try {
new ExpandableListView(null);
@@ -74,230 +107,292 @@
}
public void testSetChildDivider() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
- Drawable drawable = mContext.getResources().getDrawable(R.drawable.scenery);
- expandableListView.setChildDivider(drawable);
+ Drawable drawable = mActivity.getResources().getDrawable(R.drawable.scenery);
+ mExpandableListView.setChildDivider(drawable);
}
public void testSetAdapter() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
try {
- expandableListView.setAdapter((ListAdapter) null);
+ mExpandableListView.setAdapter((ListAdapter) null);
fail("setAdapter(ListAdapter) should throw RuntimeException here.");
} catch (RuntimeException e) {
}
}
+ @UiThreadTest
public void testGetAdapter() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
- assertNull(expandableListView.getAdapter());
+ assertNull(mExpandableListView.getAdapter());
ExpandableListAdapter expandableAdapter = new MockExpandableListAdapter();
- expandableListView.setAdapter(expandableAdapter);
- assertNotNull(expandableListView.getAdapter());
+ mExpandableListView.setAdapter(expandableAdapter);
+ assertNotNull(mExpandableListView.getAdapter());
}
+ @UiThreadTest
public void testAccessExpandableListAdapter() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
ExpandableListAdapter expandableAdapter = new MockExpandableListAdapter();
- assertNull(expandableListView.getExpandableListAdapter());
- expandableListView.setAdapter(expandableAdapter);
- assertSame(expandableAdapter, expandableListView.getExpandableListAdapter());
+ assertNull(mExpandableListView.getExpandableListAdapter());
+ mExpandableListView.setAdapter(expandableAdapter);
+ assertSame(expandableAdapter, mExpandableListView.getExpandableListAdapter());
}
+ @UiThreadTest
public void testPerformItemClick() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
+ assertFalse(mExpandableListView.performItemClick(null, 100, 99));
- assertFalse(expandableListView.performItemClick(null, 100, 99));
-
- MockOnItemClickListener onClickListener = new MockOnItemClickListener();
- expandableListView.setOnItemClickListener(onClickListener);
- assertTrue(expandableListView.performItemClick(null, 100, 99));
+ ExpandableListView.OnItemClickListener mockOnItemClickListener =
+ mock(ExpandableListView.OnItemClickListener.class);
+ mExpandableListView.setOnItemClickListener(mockOnItemClickListener);
+ assertTrue(mExpandableListView.performItemClick(null, 100, 99));
+ verify(mockOnItemClickListener, times(1)).onItemClick(eq(mExpandableListView),
+ any(View.class), eq(100), eq(99L));
}
public void testSetOnItemClickListener() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
- MockOnItemClickListener listener = new MockOnItemClickListener();
+ ExpandableListView.OnItemClickListener mockOnItemClickListener =
+ mock(ExpandableListView.OnItemClickListener.class);
- assertNull(expandableListView.getOnItemClickListener());
- expandableListView.setOnItemClickListener(listener);
- assertSame(listener, expandableListView.getOnItemClickListener());
+ assertNull(mExpandableListView.getOnItemClickListener());
+ mExpandableListView.setOnItemClickListener(mockOnItemClickListener);
+ assertSame(mockOnItemClickListener, mExpandableListView.getOnItemClickListener());
}
+ @UiThreadTest
public void testExpandGroup() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
ExpandableListAdapter expandableAdapter = new MockExpandableListAdapter();
- expandableListView.setAdapter(expandableAdapter);
+ mExpandableListView.setAdapter(expandableAdapter);
- MockOnGroupExpandListener mockOnGroupExpandListener = new MockOnGroupExpandListener();
- expandableListView.setOnGroupExpandListener(mockOnGroupExpandListener);
+ ExpandableListView.OnGroupExpandListener mockOnGroupExpandListener =
+ mock(ExpandableListView.OnGroupExpandListener.class);
+ mExpandableListView.setOnGroupExpandListener(mockOnGroupExpandListener);
- assertFalse(mockOnGroupExpandListener.hasCalledOnGroupExpand());
- assertTrue(expandableListView.expandGroup(0));
- assertTrue(mockOnGroupExpandListener.hasCalledOnGroupExpand());
- mockOnGroupExpandListener.reset();
- assertFalse(expandableListView.expandGroup(0));
- assertTrue(mockOnGroupExpandListener.hasCalledOnGroupExpand());
- mockOnGroupExpandListener.reset();
- assertTrue(expandableListView.expandGroup(1));
- assertTrue(mockOnGroupExpandListener.hasCalledOnGroupExpand());
- mockOnGroupExpandListener.reset();
- assertFalse(expandableListView.expandGroup(1));
- assertTrue(mockOnGroupExpandListener.hasCalledOnGroupExpand());
- mockOnGroupExpandListener.reset();
+ verifyZeroInteractions(mockOnGroupExpandListener);
- expandableListView.setAdapter((ExpandableListAdapter) null);
+ assertTrue(mExpandableListView.expandGroup(0));
+ verify(mockOnGroupExpandListener, times(1)).onGroupExpand(0);
+ assertTrue(mExpandableListView.isGroupExpanded(0));
+
+ reset(mockOnGroupExpandListener);
+ assertFalse(mExpandableListView.expandGroup(0));
+ verify(mockOnGroupExpandListener, times(1)).onGroupExpand(0);
+ assertTrue(mExpandableListView.isGroupExpanded(0));
+
+ reset(mockOnGroupExpandListener);
+ assertTrue(mExpandableListView.expandGroup(1));
+ verify(mockOnGroupExpandListener, times(1)).onGroupExpand(1);
+ assertTrue(mExpandableListView.isGroupExpanded(1));
+
+ reset(mockOnGroupExpandListener);
+ assertFalse(mExpandableListView.expandGroup(1));
+ verify(mockOnGroupExpandListener, times(1)).onGroupExpand(1);
+ assertTrue(mExpandableListView.isGroupExpanded(1));
+
+ reset(mockOnGroupExpandListener);
+ mExpandableListView.setAdapter((ExpandableListAdapter) null);
try {
- expandableListView.expandGroup(0);
+ mExpandableListView.expandGroup(0);
fail("should throw NullPointerException");
} catch (NullPointerException e) {
}
}
+ public void testExpandGroupSmooth() {
+ mInstrumentation.runOnMainSync(
+ () -> mExpandableListView.setAdapter(new MockExpandableListAdapter()));
+
+ ExpandableListView.OnGroupExpandListener mockOnGroupExpandListener =
+ mock(ExpandableListView.OnGroupExpandListener.class);
+ mExpandableListView.setOnGroupExpandListener(mockOnGroupExpandListener);
+
+ verifyZeroInteractions(mockOnGroupExpandListener);
+ mInstrumentation.runOnMainSync(() -> assertTrue(mExpandableListView.expandGroup(0, true)));
+ mInstrumentation.waitForIdleSync();
+ verify(mockOnGroupExpandListener, times(1)).onGroupExpand(0);
+ assertTrue(mExpandableListView.isGroupExpanded(0));
+
+ reset(mockOnGroupExpandListener);
+ mInstrumentation.runOnMainSync(() -> assertFalse(mExpandableListView.expandGroup(0, true)));
+ mInstrumentation.waitForIdleSync();
+ verify(mockOnGroupExpandListener, times(1)).onGroupExpand(0);
+ assertTrue(mExpandableListView.isGroupExpanded(0));
+
+ reset(mockOnGroupExpandListener);
+ mInstrumentation.runOnMainSync(() -> assertTrue(mExpandableListView.expandGroup(1, true)));
+ mInstrumentation.waitForIdleSync();
+ verify(mockOnGroupExpandListener, times(1)).onGroupExpand(1);
+ assertTrue(mExpandableListView.isGroupExpanded(1));
+
+ reset(mockOnGroupExpandListener);
+ mInstrumentation.runOnMainSync(() -> assertFalse(mExpandableListView.expandGroup(1, true)));
+ mInstrumentation.waitForIdleSync();
+ verify(mockOnGroupExpandListener, times(1)).onGroupExpand(1);
+ assertTrue(mExpandableListView.isGroupExpanded(1));
+
+ reset(mockOnGroupExpandListener);
+ mInstrumentation.runOnMainSync(() -> {
+ mExpandableListView.setAdapter((ExpandableListAdapter) null);
+ try {
+ mExpandableListView.expandGroup(0);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ }
+ });
+ }
+
+ @UiThreadTest
public void testCollapseGroup() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
ExpandableListAdapter expandableAdapter = new MockExpandableListAdapter();
- expandableListView.setAdapter(expandableAdapter);
+ mExpandableListView.setAdapter(expandableAdapter);
- MockOnGroupCollapseListener mockOnGroupCollapseListener =
- new MockOnGroupCollapseListener();
- expandableListView.setOnGroupCollapseListener(mockOnGroupCollapseListener);
+ ExpandableListView.OnGroupCollapseListener mockOnGroupCollapseListener =
+ mock(ExpandableListView.OnGroupCollapseListener.class);
+ mExpandableListView.setOnGroupCollapseListener(mockOnGroupCollapseListener);
- assertFalse(mockOnGroupCollapseListener.hasCalledOnGroupCollapse());
- assertFalse(expandableListView.collapseGroup(0));
- assertTrue(mockOnGroupCollapseListener.hasCalledOnGroupCollapse());
- mockOnGroupCollapseListener.reset();
+ verifyZeroInteractions(mockOnGroupCollapseListener);
+ assertFalse(mExpandableListView.collapseGroup(0));
+ verify(mockOnGroupCollapseListener, times(1)).onGroupCollapse(0);
+ assertFalse(mExpandableListView.isGroupExpanded(0));
- expandableListView.expandGroup(0);
- assertTrue(expandableListView.collapseGroup(0));
- assertTrue(mockOnGroupCollapseListener.hasCalledOnGroupCollapse());
- mockOnGroupCollapseListener.reset();
- assertFalse(expandableListView.collapseGroup(1));
- assertTrue(mockOnGroupCollapseListener.hasCalledOnGroupCollapse());
- mockOnGroupCollapseListener.reset();
+ reset(mockOnGroupCollapseListener);
+ mExpandableListView.expandGroup(0);
+ assertTrue(mExpandableListView.collapseGroup(0));
+ verify(mockOnGroupCollapseListener, times(1)).onGroupCollapse(0);
+ assertFalse(mExpandableListView.isGroupExpanded(0));
- expandableListView.setAdapter((ExpandableListAdapter) null);
+ reset(mockOnGroupCollapseListener);
+ assertFalse(mExpandableListView.collapseGroup(1));
+ verify(mockOnGroupCollapseListener, times(1)).onGroupCollapse(1);
+ assertFalse(mExpandableListView.isGroupExpanded(1));
+
+ reset(mockOnGroupCollapseListener);
+ mExpandableListView.setAdapter((ExpandableListAdapter) null);
try {
- expandableListView.collapseGroup(0);
+ mExpandableListView.collapseGroup(0);
fail("should throw NullPointerException");
} catch (NullPointerException e) {
}
}
+ @UiThreadTest
public void testSetOnGroupClickListener() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
- expandableListView.setAdapter(new MockExpandableListAdapter());
- MockOnGroupClickListener listener = new MockOnGroupClickListener();
+ mExpandableListView.setAdapter(new MockExpandableListAdapter());
- expandableListView.setOnGroupClickListener(listener);
- assertFalse(listener.hasCalledOnGroupClick());
- expandableListView.performItemClick(null, 0, 0);
- assertTrue(listener.hasCalledOnGroupClick());
+ ExpandableListView.OnGroupClickListener mockOnGroupClickListener =
+ mock(ExpandableListView.OnGroupClickListener.class);
+
+ mExpandableListView.setOnGroupClickListener(mockOnGroupClickListener);
+ verifyZeroInteractions(mockOnGroupClickListener);
+
+ mExpandableListView.performItemClick(null, 0, 0);
+ verify(mockOnGroupClickListener, times(1)).onGroupClick(eq(mExpandableListView),
+ any(View.class), eq(0), eq(0L));
}
+ @UiThreadTest
public void testSetOnChildClickListener() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
- expandableListView.setAdapter(new MockExpandableListAdapter());
- MockOnChildClickListener listener = new MockOnChildClickListener();
+ mExpandableListView.setAdapter(new MockExpandableListAdapter());
- expandableListView.setOnChildClickListener(listener);
- assertFalse(listener.hasCalledOnChildClick());
+ ExpandableListView.OnChildClickListener mockOnChildClickListener =
+ mock(ExpandableListView.OnChildClickListener.class);
+
+ mExpandableListView.setOnChildClickListener(mockOnChildClickListener);
+ verifyZeroInteractions(mockOnChildClickListener);
+
// first let the list expand
- expandableListView.expandGroup(0);
+ mExpandableListView.expandGroup(0);
// click on the child list of the first group
- expandableListView.performItemClick(null, 1, 0);
- assertTrue(listener.hasCalledOnChildClick());
+ mExpandableListView.performItemClick(null, 1, 0);
+ verify(mockOnChildClickListener, times(1)).onChildClick(eq(mExpandableListView),
+ any(View.class), eq(0), eq(0), eq(0L));
}
+ @UiThreadTest
public void testGetExpandableListPosition() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
- expandableListView.setAdapter(new MockExpandableListAdapter());
+ mExpandableListView.setAdapter(new MockExpandableListAdapter());
- assertEquals(0, expandableListView.getExpandableListPosition(0));
+ assertEquals(0, mExpandableListView.getExpandableListPosition(0));
// Group 0 is not expanded, position 1 is invalid
assertEquals(ExpandableListView.PACKED_POSITION_VALUE_NULL,
- expandableListView.getExpandableListPosition(1));
+ mExpandableListView.getExpandableListPosition(1));
// Position 1 becomes valid when group 0 is expanded
- expandableListView.expandGroup(0);
+ mExpandableListView.expandGroup(0);
assertEquals(ExpandableListView.getPackedPositionForChild(0, 0),
- expandableListView.getExpandableListPosition(1));
+ mExpandableListView.getExpandableListPosition(1));
// Position 2 is still invalid (only one child).
assertEquals(ExpandableListView.PACKED_POSITION_VALUE_NULL,
- expandableListView.getExpandableListPosition(2));
+ mExpandableListView.getExpandableListPosition(2));
}
+ @UiThreadTest
public void testGetFlatListPosition() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
- expandableListView.setAdapter(new MockExpandableListAdapter());
+ mExpandableListView.setAdapter(new MockExpandableListAdapter());
try {
- expandableListView.getFlatListPosition(ExpandableListView.PACKED_POSITION_VALUE_NULL);
+ mExpandableListView.getFlatListPosition(ExpandableListView.PACKED_POSITION_VALUE_NULL);
} catch (NullPointerException e) {
}
- assertEquals(0, expandableListView.getFlatListPosition(
+ assertEquals(0, mExpandableListView.getFlatListPosition(
ExpandableListView.PACKED_POSITION_TYPE_CHILD<<32));
// 0x8000000100000000L means this is a child and group position is 1.
- assertEquals(1, expandableListView.getFlatListPosition(0x8000000100000000L));
+ assertEquals(1, mExpandableListView.getFlatListPosition(0x8000000100000000L));
}
+ @UiThreadTest
public void testGetSelectedPosition() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
-
assertEquals(ExpandableListView.PACKED_POSITION_VALUE_NULL,
- expandableListView.getSelectedPosition());
+ mExpandableListView.getSelectedPosition());
- expandableListView.setAdapter(new MockExpandableListAdapter());
+ mExpandableListView.setAdapter(new MockExpandableListAdapter());
- expandableListView.setSelectedGroup(0);
- assertEquals(0, expandableListView.getSelectedPosition());
+ mExpandableListView.setSelectedGroup(0);
+ assertEquals(0, mExpandableListView.getSelectedPosition());
- expandableListView.setSelectedGroup(1);
- assertEquals(0, expandableListView.getSelectedPosition());
+ mExpandableListView.setSelectedGroup(1);
+ assertEquals(0, mExpandableListView.getSelectedPosition());
}
+ @UiThreadTest
public void testGetSelectedId() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
+ assertEquals(-1, mExpandableListView.getSelectedId());
+ mExpandableListView.setAdapter(new MockExpandableListAdapter());
- assertEquals(-1, expandableListView.getSelectedId());
- expandableListView.setAdapter(new MockExpandableListAdapter());
+ mExpandableListView.setSelectedGroup(0);
+ assertEquals(0, mExpandableListView.getSelectedId());
- expandableListView.setSelectedGroup(0);
- assertEquals(0, expandableListView.getSelectedId());
-
- expandableListView.setSelectedGroup(1);
- assertEquals(0, expandableListView.getSelectedId());
+ mExpandableListView.setSelectedGroup(1);
+ assertEquals(0, mExpandableListView.getSelectedId());
}
+ @UiThreadTest
public void testSetSelectedGroup() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
- expandableListView.setAdapter(new MockExpandableListAdapter());
+ mExpandableListView.setAdapter(new MockExpandableListAdapter());
- expandableListView.setSelectedGroup(0);
- assertEquals(0, expandableListView.getSelectedPosition());
+ mExpandableListView.setSelectedGroup(0);
+ assertEquals(0, mExpandableListView.getSelectedPosition());
- expandableListView.setSelectedGroup(1);
- assertEquals(0, expandableListView.getSelectedPosition());
+ mExpandableListView.setSelectedGroup(1);
+ assertEquals(0, mExpandableListView.getSelectedPosition());
}
+ @UiThreadTest
public void testSetSelectedChild() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
- expandableListView.setAdapter(new MockExpandableListAdapter());
+ mExpandableListView.setAdapter(new MockExpandableListAdapter());
- assertTrue(expandableListView.setSelectedChild(0, 0, false));
- assertTrue(expandableListView.setSelectedChild(0, 1, true));
+ assertTrue(mExpandableListView.setSelectedChild(0, 0, false));
+ assertTrue(mExpandableListView.setSelectedChild(0, 1, true));
}
+ @UiThreadTest
public void testIsGroupExpanded() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
- expandableListView.setAdapter(new MockExpandableListAdapter());
+ mExpandableListView.setAdapter(new MockExpandableListAdapter());
- expandableListView.expandGroup(1);
- assertFalse(expandableListView.isGroupExpanded(0));
- assertTrue(expandableListView.isGroupExpanded(1));
+ mExpandableListView.expandGroup(1);
+ assertFalse(mExpandableListView.isGroupExpanded(0));
+ assertTrue(mExpandableListView.isGroupExpanded(1));
}
public void testGetPackedPositionType() {
@@ -356,31 +451,35 @@
}
public void testSetChildIndicator() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
- expandableListView.setChildIndicator(null);
+ mExpandableListView.setChildIndicator(null);
}
public void testSetChildIndicatorBounds() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
- expandableListView.setChildIndicatorBounds(10, 10);
+ mExpandableListView.setChildIndicatorBounds(10, 20);
+ }
+
+ public void testSetChildIndicatorBoundsRelative() {
+ mExpandableListView.setChildIndicatorBoundsRelative(10, 20);
}
public void testSetGroupIndicator() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
Drawable drawable = new BitmapDrawable();
- expandableListView.setGroupIndicator(drawable);
+ mExpandableListView.setGroupIndicator(drawable);
}
public void testSetIndicatorBounds() {
- ExpandableListView expandableListView = new ExpandableListView(mContext);
- expandableListView.setIndicatorBounds(10,10);
+ mExpandableListView.setIndicatorBounds(10, 30);
+ }
+
+ public void testSetIndicatorBoundsRelative() {
+ mExpandableListView.setIndicatorBoundsRelative(10, 30);
}
public void testOnSaveInstanceState() {
- ExpandableListView src = new ExpandableListView(mContext);
+ ExpandableListView src = new ExpandableListView(mActivity);
Parcelable p1 = src.onSaveInstanceState();
- ExpandableListView dest = new ExpandableListView(mContext);
+ ExpandableListView dest = new ExpandableListView(mActivity);
dest.onRestoreInstanceState(p1);
Parcelable p2 = dest.onSaveInstanceState();
@@ -389,11 +488,17 @@
}
public void testDispatchDraw() {
- MockExpandableListView expandableListView = new MockExpandableListView(mContext);
+ MockExpandableListView expandableListView = new MockExpandableListView(mActivity);
expandableListView.dispatchDraw(new Canvas());
}
private class MockExpandableListAdapter implements ExpandableListAdapter {
+ private final LayoutInflater mLayoutInflater;
+
+ public MockExpandableListAdapter() {
+ mLayoutInflater = LayoutInflater.from(mActivity);
+ }
+
public void registerDataSetObserver(DataSetObserver observer) {
}
@@ -443,12 +548,24 @@
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
- return null;
+ TextView result = (TextView) convertView;
+ if (result == null) {
+ result = (TextView) mLayoutInflater.inflate(
+ R.layout.expandablelistview_group, parent, false);
+ }
+ result.setText("Group " + groupPosition);
+ return result;
}
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
- return null;
+ TextView result = (TextView) convertView;
+ if (result == null) {
+ result = (TextView) mLayoutInflater.inflate(
+ R.layout.expandablelistview_child, parent, false);
+ }
+ result.setText("Child " + childPosition);
+ return result;
}
public boolean isChildSelectable(int groupPosition, int childPosition) {
@@ -478,72 +595,6 @@
}
}
- private class MockOnGroupExpandListener implements ExpandableListView.OnGroupExpandListener {
- private boolean mCalledOnGroupExpand = false;
-
- public void onGroupExpand(int groupPosition) {
- mCalledOnGroupExpand = true;
- }
-
- public boolean hasCalledOnGroupExpand() {
- return mCalledOnGroupExpand;
- }
-
- public void reset() {
- mCalledOnGroupExpand = false;
- }
- }
-
- private class MockOnGroupCollapseListener implements
- ExpandableListView.OnGroupCollapseListener {
- private boolean mCalledOnGroupCollapse = false;
-
- public void onGroupCollapse(int groupPosition) {
- mCalledOnGroupCollapse = true;
- }
-
- public boolean hasCalledOnGroupCollapse() {
- return mCalledOnGroupCollapse;
- }
-
- public void reset() {
- mCalledOnGroupCollapse = false;
- }
- }
-
- private class MockOnItemClickListener implements OnItemClickListener {
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- }
- }
-
- private class MockOnGroupClickListener implements OnGroupClickListener {
- private boolean mCalledOnGroupClick = false;
-
- public boolean onGroupClick(ExpandableListView parent, View v,
- int groupPosition, long id) {
- mCalledOnGroupClick = true;
- return true;
- }
-
- public boolean hasCalledOnGroupClick() {
- return mCalledOnGroupClick;
- }
- }
-
- private class MockOnChildClickListener implements OnChildClickListener {
- private boolean mCalledOnChildClick = false;
-
- public boolean onChildClick(ExpandableListView parent, View v,
- int groupPosition, int childPosition, long id) {
- mCalledOnChildClick = true;
- return true;
- }
-
- public boolean hasCalledOnChildClick() {
- return mCalledOnChildClick;
- }
- }
-
private class MockExpandableListView extends ExpandableListView {
public MockExpandableListView(Context context) {
super(context);
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListViewWithHeadersTest.java b/tests/tests/widget/src/android/widget/cts/ExpandableListViewWithHeadersTest.java
index 7f4715f..9cbc92e 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListViewWithHeadersTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListViewWithHeadersTest.java
@@ -39,12 +39,7 @@
super.setUp();
final ExpandableListWithHeaders activity = getActivity();
- new PollingCheck() {
- @Override
- protected boolean check() {
- return activity.hasWindowFocus();
- }
- }.run();
+ PollingCheck.waitFor(() -> activity.hasWindowFocus());
mExpandableListView = activity.getExpandableListView();
mListUtil = new ListUtil(mExpandableListView, getInstrumentation());
}
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListWithHeaders.java b/tests/tests/widget/src/android/widget/cts/ExpandableListWithHeaders.java
index 259d443..17e8a59 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListWithHeaders.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListWithHeaders.java
@@ -22,14 +22,14 @@
import android.widget.cts.util.ExpandableListScenario;
public class ExpandableListWithHeaders extends ExpandableListScenario {
- private static final int[] sNumChildren = {1, 4, 3, 2, 6};
- private static final int sNumOfHeadersAndFooters = 12;
+ private static final int[] CHILD_COUNT = {1, 4, 3, 2, 6};
+ private static final int HEADER_FOOTER_COUNT = 12;
@Override
protected void init(ExpandableParams params) {
params.setStackFromBottom(false)
.setStartingSelectionPosition(-1)
- .setNumChildren(sNumChildren)
+ .setNumChildren(CHILD_COUNT)
.setItemScreenSizeFactor(0.14)
.setConnectAdapter(false);
}
@@ -41,13 +41,13 @@
final ExpandableListView expandableListView = getExpandableListView();
expandableListView.setItemsCanFocus(true);
- for (int i = 0; i < sNumOfHeadersAndFooters; i++) {
+ for (int i = 0; i < HEADER_FOOTER_COUNT; i++) {
Button header = new Button(this);
header.setText("Header View");
expandableListView.addHeaderView(header);
}
- for (int i = 0; i < sNumOfHeadersAndFooters; i++) {
+ for (int i = 0; i < HEADER_FOOTER_COUNT; i++) {
Button footer = new Button(this);
footer.setText("Footer View");
expandableListView.addFooterView(footer);
@@ -61,6 +61,6 @@
* @return The number of headers (and the same number of footers)
*/
public int getNumOfHeadersAndFooters() {
- return sNumOfHeadersAndFooters;
+ return HEADER_FOOTER_COUNT;
}
}
diff --git a/tests/tests/widget/src/android/widget/cts/FilterTest.java b/tests/tests/widget/src/android/widget/cts/FilterTest.java
index 7a1d111..77c73f3 100644
--- a/tests/tests/widget/src/android/widget/cts/FilterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/FilterTest.java
@@ -24,6 +24,16 @@
import android.test.ActivityInstrumentationTestCase2;
import android.widget.Filter;
import android.widget.Filter.FilterListener;
+import org.junit.Assert;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
public class FilterTest extends ActivityInstrumentationTestCase2<CtsActivity> {
private static final long TIME_OUT = 10000;
@@ -66,26 +76,22 @@
});
getInstrumentation().waitForIdleSync();
- new PollingCheck(TIME_OUT) {
- @Override
- protected boolean check() {
- return mMockFilter.hadPerformedFiltering();
- }
- }.run();
+ PollingCheck.waitFor(TIME_OUT, () -> mMockFilter.hadPerformedFiltering());
assertEquals(TEST_CONSTRAINT, mMockFilter.getPerformFilteringConstraint());
- new PollingCheck(TIME_OUT) {
- @Override
- protected boolean check() {
- return mMockFilter.hadPublishedResults();
- }
- }.run();
+ PollingCheck.waitFor(TIME_OUT, () -> mMockFilter.hadPublishedResults());
assertEquals(TEST_CONSTRAINT, mMockFilter.getPublishResultsConstraint());
assertSame(mMockFilter.getExpectResults(), mMockFilter.getResults());
}
public void testFilter2() {
- final MockFilterListener mockFilterListener = new MockFilterListener();
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
+ final Filter.FilterListener mockFilterListener = mock(Filter.FilterListener.class);
+ doAnswer((InvocationOnMock invocation) -> {
+ countDownLatch.countDown();
+ return null;
+ }).when(mockFilterListener).onFilterComplete(anyInt());
+
getActivity().runOnUiThread(new Runnable() {
public void run() {
mMockFilter = new MockFilter();
@@ -94,29 +100,18 @@
});
getInstrumentation().waitForIdleSync();
- new PollingCheck(TIME_OUT) {
- @Override
- protected boolean check() {
- return mMockFilter.hadPerformedFiltering();
- }
- }.run();
+ PollingCheck.waitFor(TIME_OUT, () -> mMockFilter.hadPerformedFiltering());
assertEquals(TEST_CONSTRAINT, mMockFilter.getPerformFilteringConstraint());
- new PollingCheck(TIME_OUT) {
- @Override
- protected boolean check() {
- return mMockFilter.hadPublishedResults();
- }
- }.run();
+ PollingCheck.waitFor(TIME_OUT, () -> mMockFilter.hadPublishedResults());
assertEquals(TEST_CONSTRAINT, mMockFilter.getPublishResultsConstraint());
assertSame(mMockFilter.getExpectResults(), mMockFilter.getResults());
- new PollingCheck(TIME_OUT) {
- @Override
- protected boolean check() {
- return mockFilterListener.hasCalledOnFilterComplete();
- }
- }.run();
+ try {
+ countDownLatch.await(TIME_OUT, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException ie) {
+ Assert.fail(ie.toString());
+ }
}
private static class MockFilter extends Filter {
@@ -185,16 +180,4 @@
}
}
}
-
- private static class MockFilterListener implements FilterListener {
- private boolean mCalledOnFilterComplete = false;
-
- public void onFilterComplete(int count) {
- mCalledOnFilterComplete = true;
- }
-
- public boolean hasCalledOnFilterComplete() {
- return mCalledOnFilterComplete;
- }
- }
}
diff --git a/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java b/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
index 4309dbb..f4ac880 100644
--- a/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
@@ -16,6 +16,9 @@
package android.widget.cts;
+import android.graphics.drawable.ColorDrawable;
+import android.test.suitebuilder.annotation.SmallTest;
+import org.mockito.ArgumentCaptor;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -49,6 +52,10 @@
import java.io.IOException;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
+
+@SmallTest
public class FrameLayoutTest extends ActivityInstrumentationTestCase2<FrameLayoutCtsActivity> {
private Activity mActivity;
private Instrumentation mInstrumentation;
@@ -94,17 +101,12 @@
assertTrue(foreground.isVisible());
final Rect rect = foreground.getBounds();
// foreground has been stretched
- new PollingCheck() {
- @Override
- protected boolean check() {
- return mFrameLayout.getHeight() == rect.bottom - rect.top;
- }
- }.run();
+ PollingCheck.waitFor(() -> mFrameLayout.getHeight() == rect.bottom - rect.top);
assertEquals(mFrameLayout.getWidth(), rect.right - rect.left);
// should get a new foreground again, because former foreground has been stretched
final BitmapDrawable newForeground =
- (BitmapDrawable) mActivity.getResources().getDrawable(R.drawable.size_48x48);
+ (BitmapDrawable) mActivity.getDrawable(R.drawable.size_48x48);
compareScaledPixels(48, newForeground.getIntrinsicHeight());
compareScaledPixels(48, newForeground.getIntrinsicWidth());
assertTrue(mFrameLayout.getHeight() > newForeground.getIntrinsicHeight());
@@ -156,7 +158,7 @@
assertEquals(textView.getMeasuredWidth(), frameLayout.getMeasuredWidth());
// measureAll is false and text view is GONE, text view will NOT be measured
- mActivity.runOnUiThread(() -> {
+ mInstrumentation.runOnMainSync(() -> {
textView.setVisibility(View.GONE);
frameLayout.requestLayout();
});
@@ -169,11 +171,12 @@
assertEquals(button.getMeasuredWidth(), frameLayout.getMeasuredWidth());
// measureAll is true and text view is GONE, text view will be measured
- mActivity.runOnUiThread(() -> {
+ mInstrumentation.runOnMainSync(() -> {
frameLayout.setMeasureAllChildren(true);
frameLayout.requestLayout();
});
mInstrumentation.waitForIdleSync();
+ assertTrue(frameLayout.getMeasureAllChildren());
assertTrue(frameLayout.getConsiderGoneChildrenWhenMeasuring());
assertEquals(textView.getMeasuredHeight(), frameLayout.getMeasuredHeight());
assertEquals(textView.getMeasuredWidth(), frameLayout.getMeasuredWidth());
@@ -285,21 +288,25 @@
assertEquals("Foreground tint mode inflated correctly",
PorterDuff.Mode.SRC_OVER, inflatedView.getForegroundTintMode());
- MockDrawable foreground = new MockDrawable();
+ final Drawable foreground = spy(new ColorDrawable());
FrameLayout view = new FrameLayout(mActivity);
view.setForeground(foreground);
- assertFalse("No foreground tint applied by default", foreground.hasCalledSetTint());
+ verify(foreground, never()).setTintList(any(ColorStateList.class));
- view.setForegroundTintList(ColorStateList.valueOf(Color.WHITE));
- assertTrue("Foreground tint applied when setForegroundTintList() called after setForeground()",
- foreground.hasCalledSetTint());
+ view.setForegroundTintList(ColorStateList.valueOf(Color.RED));
+ final ArgumentCaptor<ColorStateList> colorStateListCaptor =
+ ArgumentCaptor.forClass(ColorStateList.class);
+ verify(foreground, times(1)).setTintList(colorStateListCaptor.capture());
+ assertEquals(1, colorStateListCaptor.getValue().getColors().length);
+ assertEquals(Color.RED, colorStateListCaptor.getValue().getColors()[0]);
- foreground.reset();
+ reset(foreground);
view.setForeground(null);
view.setForeground(foreground);
- assertTrue("Foreground tint applied when setForegroundTintList() called before setForeground()",
- foreground.hasCalledSetTint());
+ verify(foreground, times(1)).setTintList(colorStateListCaptor.capture());
+ assertEquals(1, colorStateListCaptor.getValue().getColors().length);
+ assertEquals(Color.RED, colorStateListCaptor.getValue().getColors()[0]);
}
private static void assertCenterAligned(View container, Drawable drawable) {
@@ -319,38 +326,6 @@
return Xml.asAttributeSet(parser);
}
- private static class MockDrawable extends Drawable {
- private boolean mCalledSetTint = false;
-
- @Override
- public void draw(Canvas canvas) {}
-
- @Override
- public void setAlpha(int alpha) {}
-
- @Override
- public void setColorFilter(ColorFilter cf) {}
-
- @Override
- public void setTintList(ColorStateList tint) {
- super.setTintList(tint);
- mCalledSetTint = true;
- }
-
- @Override
- public int getOpacity() {
- return 0;
- }
-
- public boolean hasCalledSetTint() {
- return mCalledSetTint;
- }
-
- public void reset() {
- mCalledSetTint = false;
- }
- }
-
private static class MyFrameLayout extends FrameLayout {
public MyFrameLayout(Context context) {
super(context);
diff --git a/tests/tests/widget/src/android/widget/cts/GalleryTest.java b/tests/tests/widget/src/android/widget/cts/GalleryTest.java
index dd39461..5394319 100644
--- a/tests/tests/widget/src/android/widget/cts/GalleryTest.java
+++ b/tests/tests/widget/src/android/widget/cts/GalleryTest.java
@@ -16,40 +16,29 @@
package android.widget.cts;
-import android.widget.cts.R;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.app.Activity;
import android.app.Instrumentation;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
import android.cts.util.WidgetTestUtils;
-import android.graphics.drawable.Drawable;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
import android.test.ViewAsserts;
import android.util.AttributeSet;
import android.util.Xml;
-import android.view.ContextMenu;
import android.view.Gravity;
import android.view.KeyEvent;
-import android.view.MenuItem;
-import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Transformation;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
-import android.widget.AdapterView.OnItemSelectedListener;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
@@ -348,37 +337,4 @@
R.drawable.testimage,
};
}
-
- private static class MockOnItemSelectedListener implements OnItemSelectedListener {
- private boolean mIsItemSelected;
- private boolean mNothingSelected;
- private int mItemSelectedCalledCount;
-
- public boolean isItemSelected() {
- return mIsItemSelected;
- }
-
- public boolean hasNothingSelected() {
- return mNothingSelected;
- }
-
- public int getItemSelectedCalledCount() {
- return mItemSelectedCalledCount;
- }
-
- public void reset() {
- mIsItemSelected = false;
- mNothingSelected = true;
- mItemSelectedCalledCount = 0;
- }
-
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- mIsItemSelected = true;
- mItemSelectedCalledCount++;
- }
-
- public void onNothingSelected(AdapterView<?> parent) {
- mNothingSelected = true;
- }
- }
}
diff --git a/tests/tests/widget/src/android/widget/cts/GridViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/GridViewCtsActivity.java
index 7b2e7a3..47ad5d8 100644
--- a/tests/tests/widget/src/android/widget/cts/GridViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/GridViewCtsActivity.java
@@ -16,17 +16,16 @@
package android.widget.cts;
-import android.widget.cts.R;
-
import android.app.Activity;
import android.os.Bundle;
+import android.widget.GridView;
/**
* A minimal application for {@link GridView} test.
*/
public class GridViewCtsActivity extends Activity {
/**
- * Called with the activity is first created.
+ * Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
diff --git a/tests/tests/widget/src/android/widget/cts/GridViewTest.java b/tests/tests/widget/src/android/widget/cts/GridViewTest.java
index 7b83416..e770395 100644
--- a/tests/tests/widget/src/android/widget/cts/GridViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/GridViewTest.java
@@ -16,12 +16,6 @@
package android.widget.cts;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
@@ -30,9 +24,11 @@
import android.database.DataSetObserver;
import android.graphics.Rect;
import android.test.ActivityInstrumentationTestCase;
-import android.test.TouchUtils;
import android.test.UiThreadTest;
import android.test.ViewAsserts;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
import android.util.AttributeSet;
import android.util.Xml;
import android.view.Gravity;
@@ -47,12 +43,23 @@
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListAdapter;
-import android.widget.AdapterView.OnItemClickListener;
import android.widget.cts.util.ViewTestUtils;
+import org.xmlpull.v1.XmlPullParser;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.*;
+
/**
* Test {@link GridView}.
*/
+@SmallTest
public class GridViewTest extends ActivityInstrumentationTestCase<GridViewCtsActivity> {
private GridView mGridView;
private Activity mActivity;
@@ -62,22 +69,15 @@
super("android.widget.cts", GridViewCtsActivity.class);
}
- private GridView findGridViewById(int id) {
- return (GridView) mActivity.findViewById(id);
- }
-
@Override
protected void setUp() throws Exception {
super.setUp();
- mGridView = null;
- mActivity = getActivity();
- new PollingCheck() {
- @Override
- protected boolean check() {
- return mActivity.hasWindowFocus();
- }
- }.run();
+
mInstrumentation = getInstrumentation();
+ mActivity = getActivity();
+ mGridView = (GridView) mActivity.findViewById(R.id.gridview);
+
+ PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
}
public void testConstructor() {
@@ -87,6 +87,14 @@
new GridView(mActivity, null, android.R.attr.gridViewStyle);
+ new GridView(mActivity, null, 0, android.R.style.Widget_DeviceDefault_GridView);
+
+ new GridView(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_GridView);
+
+ new GridView(mActivity, null, 0, android.R.style.Widget_Material_GridView);
+
+ new GridView(mActivity, null, 0, android.R.style.Widget_Material_Light_GridView);
+
XmlPullParser parser = mActivity.getResources().getXml(R.layout.gridview_layout);
AttributeSet attrs = Xml.asAttributeSet(parser);
new GridView(mActivity, attrs);
@@ -111,8 +119,8 @@
}
}
+ @UiThreadTest
public void testAccessAdapter() {
- mGridView = new GridView(mActivity);
// set Adapter
ImageAdapter adapter = new ImageAdapter(mActivity);
mGridView.setAdapter(adapter);
@@ -122,8 +130,8 @@
assertNull(mGridView.getAdapter());
}
+ @UiThreadTest
public void testSetSelection() {
- mGridView = new GridView(mActivity);
mGridView.setSelection(0);
assertEquals(0, mGridView.getSelectedItemPosition());
@@ -136,10 +144,10 @@
public void testPressKey() {
final int NUM_COLUMNS = 3;
- mGridView = findGridViewById(R.id.gridview);
- MockOnItemClickListener listener = new MockOnItemClickListener();
- mGridView.setOnItemClickListener(listener);
+ GridView.OnItemClickListener mockItemClickListener =
+ mock(GridView.OnItemClickListener.class);
+ mGridView.setOnItemClickListener(mockItemClickListener);
// this test case can not be ran in UI thread.
mActivity.runOnUiThread(new Runnable() {
@@ -172,20 +180,19 @@
mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
assertEquals(NUM_COLUMNS, mGridView.getSelectedItemPosition());
- assertFalse(listener.hasOnItemClickCalled());
+ verify(mockItemClickListener, never()).onItemClick(any(AdapterView.class), any(View.class),
+ anyInt(), anyLong());
mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
- assertTrue(listener.hasOnItemClickCalled());
+ verify(mockItemClickListener, times(1)).onItemClick(eq(mGridView), any(View.class),
+ eq(NUM_COLUMNS), eq((long) NUM_COLUMNS));
- listener.reset();
- assertFalse(listener.hasOnItemClickCalled());
+ reset(mockItemClickListener);
mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER);
- assertTrue(listener.hasOnItemClickCalled());
+ verify(mockItemClickListener, times(1)).onItemClick(eq(mGridView), any(View.class),
+ eq(NUM_COLUMNS), eq((long) NUM_COLUMNS));
}
public void testSetGravity() {
- mGridView = findGridViewById(R.id.gridview);
-
- View child;
final int NUM_COLUMNS = 1;
// this test case can not be ran in UI thread.
mActivity.runOnUiThread(new Runnable() {
@@ -207,8 +214,8 @@
});
mInstrumentation.waitForIdleSync();
- child = mGridView.getChildAt(0); // get the first view.
- ViewAsserts.assertHorizontalCenterAligned(mGridView, child);
+ assertEquals(Gravity.CENTER_HORIZONTAL, mGridView.getGravity());
+ ViewAsserts.assertHorizontalCenterAligned(mGridView, mGridView.getChildAt(0));
mActivity.runOnUiThread(new Runnable() {
public void run() {
@@ -219,8 +226,9 @@
});
mInstrumentation.waitForIdleSync();
- child = mGridView.getChildAt(0); // get the first view.
- ViewAsserts.assertLeftAligned(mGridView, child, mGridView.getListPaddingLeft());
+ assertEquals(Gravity.LEFT, mGridView.getGravity());
+ ViewAsserts.assertLeftAligned(mGridView, mGridView.getChildAt(0),
+ mGridView.getListPaddingLeft());
mActivity.runOnUiThread(new Runnable() {
public void run() {
@@ -231,41 +239,34 @@
});
mInstrumentation.waitForIdleSync();
- child = mGridView.getChildAt(0); // get the first view.
- ViewAsserts.assertRightAligned(mGridView, child, mGridView.getListPaddingRight());
+ assertEquals(Gravity.RIGHT, mGridView.getGravity());
+ ViewAsserts.assertRightAligned(mGridView, mGridView.getChildAt(0),
+ mGridView.getListPaddingRight());
}
- public void testSetHorizontalSpacing() {
- testSetHorizontalSpacing(View.LAYOUT_DIRECTION_LTR);
+ public void testAccessHorizontalSpacing() {
+ verifyAccessHorizontalSpacing(View.LAYOUT_DIRECTION_LTR);
}
- public void testSetHorizontalSpacingRTL() {
- testSetHorizontalSpacing(View.LAYOUT_DIRECTION_RTL);
+ public void testAccessHorizontalSpacingRTL() {
+ verifyAccessHorizontalSpacing(View.LAYOUT_DIRECTION_RTL);
}
- public void testSetHorizontalSpacing(final int layoutDir) {
- mGridView = findGridViewById(R.id.gridview);
- mActivity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mGridView.setLayoutDirection(layoutDir);
- }
- });
+ private void verifyAccessHorizontalSpacing(final int layoutDir) {
+ mActivity.runOnUiThread(() -> mGridView.setLayoutDirection(layoutDir));
mGridView.setStretchMode(GridView.NO_STRETCH);
// Number of columns should be big enough, otherwise the
// horizontal spacing cannot be correctly verified.
mGridView.setNumColumns(28);
-
- // this test case can not be ran in UI thread.
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- mGridView.setAdapter(new MockGridViewAdapter(3));
- mGridView.setHorizontalSpacing(0);
- }
+ mActivity.runOnUiThread(() -> {
+ mGridView.setAdapter(new MockGridViewAdapter(3));
+ mGridView.setHorizontalSpacing(0);
});
mInstrumentation.waitForIdleSync();
+ assertEquals(0, mGridView.getRequestedHorizontalSpacing());
+ assertEquals(0, mGridView.getHorizontalSpacing());
View child0 = mGridView.getChildAt(0);
View child1 = mGridView.getChildAt(1);
if (layoutDir == View.LAYOUT_DIRECTION_LTR) {
@@ -274,13 +275,11 @@
assertEquals(0, child0.getLeft() - child1.getRight());
}
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- mGridView.setHorizontalSpacing(5);
- }
- });
+ mActivity.runOnUiThread(() -> mGridView.setHorizontalSpacing(5));
mInstrumentation.waitForIdleSync();
+ assertEquals(5, mGridView.getRequestedHorizontalSpacing());
+ assertEquals(5, mGridView.getHorizontalSpacing());
child0 = mGridView.getChildAt(0);
child1 = mGridView.getChildAt(1);
if (layoutDir == View.LAYOUT_DIRECTION_LTR) {
@@ -290,36 +289,28 @@
}
}
- public void testSetVerticalSpacing() {
- mGridView = findGridViewById(R.id.gridview);
-
- // this test case can not be ran in UI thread.
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- mGridView.setAdapter(new MockGridViewAdapter(3));
- mGridView.setVerticalSpacing(0);
- }
+ public void testAccessVerticalSpacing() {
+ mActivity.runOnUiThread(() -> {
+ mGridView.setAdapter(new MockGridViewAdapter(3));
+ mGridView.setVerticalSpacing(0);
});
mInstrumentation.waitForIdleSync();
+ assertEquals(0, mGridView.getVerticalSpacing());
View child0 = mGridView.getChildAt(0);
View child1 = mGridView.getChildAt(1);
assertEquals(0, child1.getTop() - child0.getBottom());
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- mGridView.setVerticalSpacing(5);
- }
- });
+ mActivity.runOnUiThread(() -> mGridView.setVerticalSpacing(5));
mInstrumentation.waitForIdleSync();
+ assertEquals(5, mGridView.getVerticalSpacing());
child0 = mGridView.getChildAt(0);
child1 = mGridView.getChildAt(1);
assertEquals(5, child1.getTop() - child0.getBottom());
}
public void testAccessStretchMode() {
- mGridView = findGridViewById(R.id.gridview);
View child;
final int NUM_COLUMNS = 8;
@@ -417,8 +408,6 @@
}
public void testSetNumColumns() {
- mGridView = findGridViewById(R.id.gridview);
-
// this test case can not be ran in UI thread.
mActivity.runOnUiThread(new Runnable() {
public void run() {
@@ -459,13 +448,12 @@
}
}
+ public void testDefaultNumColumns() {
+ final GridView gridView = new GridView(mActivity);
+ assertEquals(gridView.getNumColumns(), GridView.AUTO_FIT);
+ }
+
public void testGetNumColumns() {
- mGridView = new GridView(mActivity);
-
- assertEquals(mGridView.getNumColumns(), GridView.AUTO_FIT);
-
- mGridView = findGridViewById(R.id.gridview);
-
mActivity.runOnUiThread(new Runnable() {
public void run() {
mGridView.setAdapter(new MockGridViewAdapter(10));
@@ -532,36 +520,33 @@
// Do not test it. It's implementation detail.
}
- public void testSetColumnWidth() {
- mGridView = findGridViewById(R.id.gridview);
-
- // this test case can not be ran in UI thread.
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- mGridView.setAdapter(new MockGridViewAdapter(10));
- mGridView.setNumColumns(GridView.AUTO_FIT);
- mGridView.setHorizontalSpacing(0);
- mGridView.setVerticalSpacing(0);
- mGridView.setColumnWidth(0);
- }
+ public void testAccessColumnWidth() {
+ mActivity.runOnUiThread(() -> {
+ mGridView.setAdapter(new MockGridViewAdapter(10));
+ mGridView.setNumColumns(GridView.AUTO_FIT);
+ mGridView.setHorizontalSpacing(0);
+ mGridView.setVerticalSpacing(0);
+ mGridView.setColumnWidth(0);
});
mInstrumentation.waitForIdleSync();
// Verify whether column number equals 2.
+ assertEquals(0, mGridView.getRequestedColumnWidth());
+ assertEquals(mGridView.getWidth() / 2, mGridView.getColumnWidth());
View child0 = mGridView.getChildAt(0);
View child1 = mGridView.getChildAt(1);
View child2 = mGridView.getChildAt(2);
assertEquals(child0.getBottom(), child1.getBottom());
assertEquals(child0.getLeft(), child2.getLeft());
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- mGridView.setNumColumns(GridView.AUTO_FIT);
- mGridView.setColumnWidth(Integer.MAX_VALUE);
- }
+ mActivity.runOnUiThread(() -> {
+ mGridView.setNumColumns(GridView.AUTO_FIT);
+ mGridView.setColumnWidth(Integer.MAX_VALUE);
});
mInstrumentation.waitForIdleSync();
+ assertEquals(Integer.MAX_VALUE, mGridView.getRequestedColumnWidth());
+ assertEquals(mGridView.getWidth(), mGridView.getColumnWidth());
child0 = mGridView.getChildAt(0);
child1 = mGridView.getChildAt(1);
assertEquals(child0.getBottom(), child1.getTop());
@@ -570,7 +555,6 @@
@MediumTest
public void testFullyDetachUnusedViewOnScroll() {
- mGridView = findGridViewById(R.id.gridview);
final AttachDetachAwareView theView = new AttachDetachAwareView(mActivity);
ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, () -> {
mGridView.setAdapter(new DummyAdapter(1000, theView));
@@ -596,7 +580,6 @@
@MediumTest
public void testFullyDetachUnusedViewOnReLayout() {
- mGridView = findGridViewById(R.id.gridview);
final AttachDetachAwareView theView = new AttachDetachAwareView(mActivity);
ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, () -> {
mGridView.setAdapter(new DummyAdapter(1000, theView));
@@ -620,7 +603,6 @@
@MediumTest
public void testFullyDetachUnusedViewOnScrollForFocus() {
- mGridView = findGridViewById(R.id.gridview);
final AttachDetachAwareView theView = new AttachDetachAwareView(mActivity);
ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, () -> {
mGridView.setAdapter(new DummyAdapter(1000, theView));
@@ -639,24 +621,63 @@
ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, null);
}
assertEquals("the view should be re-attached", 2, theView.mOnAttachCount);
- assertEquals("the view should not recieve another detach", 1, theView.mOnDetachCount);
+ assertEquals("the view should not receive another detach", 1, theView.mOnDetachCount);
assertFalse(theView.isTemporarilyDetached());
}
- private static class MockGridView extends GridView {
- private boolean mCalledOnMeasure = false;
- private boolean mCalledOnFocusChanged = false;
+ @LargeTest
+ public void testSmoothScrollByOffset() {
+ final int itemCount = 300;
+ mActivity.runOnUiThread(() -> {
+ mGridView.setAdapter(new MockGridViewAdapter(itemCount));
+ mGridView.setNumColumns(GridView.AUTO_FIT);
+ mGridView.setHorizontalSpacing(0);
+ mGridView.setVerticalSpacing(0);
+ mGridView.setColumnWidth(Integer.MAX_VALUE);
+ });
+ mInstrumentation.waitForIdleSync();
- public boolean hasCalledOnMeasure() {
- return mCalledOnMeasure;
+ assertEquals(0, mGridView.getFirstVisiblePosition());
+
+ // Register a scroll listener on our GridView. The listener will notify our latch
+ // when the "target" item comes into view. If that never happens, the latch will
+ // time out and fail the test.
+ final CountDownLatch latch = new CountDownLatch(1);
+ final int positionToScrollTo = itemCount - 10;
+ mGridView.setOnScrollListener(new AbsListView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+ }
+
+ @Override
+ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+ int totalItemCount) {
+ if ((positionToScrollTo >= firstVisibleItem) &&
+ (positionToScrollTo <= (firstVisibleItem + visibleItemCount))) {
+ latch.countDown();
+ }
+ }
+ });
+ int offset = positionToScrollTo - mGridView.getLastVisiblePosition();
+ mActivity.runOnUiThread(() -> mGridView.smoothScrollByOffset(offset));
+
+ boolean result = false;
+ try {
+ result = latch.await(20, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ // ignore
}
+ assertTrue("Timed out while waiting for the target view to be scrolled into view", result);
+ }
+
+ private static class MockGridView extends GridView {
+ private boolean mCalledOnFocusChanged = false;
public boolean hasCalledOnFocusChanged() {
return mCalledOnFocusChanged;
}
public void reset() {
- mCalledOnMeasure = false;
mCalledOnFocusChanged = false;
}
@@ -684,48 +705,11 @@
}
@Override
- protected int computeVerticalScrollExtent() {
- return super.computeVerticalScrollExtent();
- }
-
- @Override
- protected int computeVerticalScrollOffset() {
- return super.computeVerticalScrollOffset();
- }
-
- @Override
- protected int computeVerticalScrollRange() {
- return super.computeVerticalScrollRange();
- }
-
- @Override
protected void onFocusChanged(boolean gainFocus, int direction,
Rect previouslyFocusedRect) {
mCalledOnFocusChanged = true;
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
}
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- mCalledOnMeasure = true;
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
- }
-
- class MockOnItemClickListener implements OnItemClickListener {
- private boolean mOnItemClickCalled = false;
-
- public boolean hasOnItemClickCalled() {
- return mOnItemClickCalled;
- }
-
- public void reset() {
- mOnItemClickCalled = false;
- }
-
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- mOnItemClickCalled = true;
- }
}
private class MockGridViewAdapter implements ListAdapter, Filterable {
@@ -735,10 +719,6 @@
mCount = count;
}
- MockGridViewAdapter() {
- this(1);
- }
-
public boolean areAllItemsEnabled() {
return true;
}
diff --git a/tests/tests/widget/src/android/widget/cts/HeaderViewListAdapterTest.java b/tests/tests/widget/src/android/widget/cts/HeaderViewListAdapterTest.java
index 2b92a4d..426fe5aa 100644
--- a/tests/tests/widget/src/android/widget/cts/HeaderViewListAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/HeaderViewListAdapterTest.java
@@ -31,6 +31,8 @@
import java.util.ArrayList;
+import static org.mockito.Mockito.mock;
+
/**
* Test {@link HeaderViewListAdapter}.
*/
@@ -334,21 +336,21 @@
HeaderViewFullAdapter fullAdapter = new HeaderViewFullAdapter();
HeaderViewListAdapter headerViewListAdapter =
new HeaderViewListAdapter(null, null, fullAdapter);
- DataSetObserver observer = new HeaderViewDataSetObserver();
- headerViewListAdapter.registerDataSetObserver(observer);
- assertSame(observer, fullAdapter.getDataSetObserver());
+ DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
+ headerViewListAdapter.registerDataSetObserver(mockDataSetObserver);
+ assertSame(mockDataSetObserver, fullAdapter.getDataSetObserver());
}
public void testUnregisterDataSetObserver() {
HeaderViewFullAdapter fullAdapter = new HeaderViewFullAdapter();
HeaderViewListAdapter headerViewListAdapter =
new HeaderViewListAdapter(null, null, fullAdapter);
- DataSetObserver observer = new HeaderViewDataSetObserver();
- headerViewListAdapter.registerDataSetObserver(observer);
+ DataSetObserver mockDataSetObserver = mock(DataSetObserver.class);
+ headerViewListAdapter.registerDataSetObserver(mockDataSetObserver);
headerViewListAdapter.unregisterDataSetObserver(null);
- assertSame(observer, fullAdapter.getDataSetObserver());
- headerViewListAdapter.unregisterDataSetObserver(observer);
+ assertSame(mockDataSetObserver, fullAdapter.getDataSetObserver());
+ headerViewListAdapter.unregisterDataSetObserver(mockDataSetObserver);
assertNull(fullAdapter.getDataSetObserver());
}
@@ -504,16 +506,4 @@
protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
}
}
-
- private class HeaderViewDataSetObserver extends DataSetObserver {
- @Override
- public void onChanged() {
- // Do nothing
- }
-
- @Override
- public void onInvalidated() {
- // Do nothing
- }
- }
}
diff --git a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
index afdc869..7a5f8f1 100644
--- a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
@@ -16,12 +16,6 @@
package android.widget.cts;
-import android.widget.FrameLayout;
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
import android.app.Activity;
import android.content.Context;
import android.cts.util.PollingCheck;
@@ -32,10 +26,14 @@
import android.util.AttributeSet;
import android.util.Xml;
import android.view.View;
-import android.view.ViewGroup;
import android.view.View.MeasureSpec;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.TextView;
+
+import org.xmlpull.v1.XmlPullParser;
+
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -800,55 +798,34 @@
}
if (fromY != toY) {
- new PollingCheck() {
- @Override
- protected boolean check() {
- return isInRange(mScrollView.getScrollY(), fromY, toY);
- }
- }.run();
+ PollingCheck.waitFor(() -> isInRange(mScrollView.getScrollY(), fromY, toY));
}
if (fromX != toX) {
- new PollingCheck() {
- @Override
- protected boolean check() {
- return isInRange(mScrollView.getScrollX(), fromX, toX);
- }
- }.run();
+ PollingCheck.waitFor(() -> isInRange(mScrollView.getScrollX(), fromX, toX));
}
- new PollingCheck() {
- @Override
- protected boolean check() {
- return toX == mScrollView.getScrollX() && toY == mScrollView.getScrollY();
- }
- }.run();
+ PollingCheck.waitFor(
+ () -> toX == mScrollView.getScrollX() && toY == mScrollView.getScrollY());
}
private void pollingCheckFling(final int startPosition, final boolean movingRight) {
- new PollingCheck() {
- @Override
- protected boolean check() {
- if (movingRight) {
- return mScrollView.getScrollX() > startPosition;
- }
- return mScrollView.getScrollX() < startPosition;
+ PollingCheck.waitFor(() -> {
+ if (movingRight) {
+ return mScrollView.getScrollX() > startPosition;
}
- }.run();
+ return mScrollView.getScrollX() < startPosition;
+ });
- new PollingCheck() {
- private int mPreviousScrollX = mScrollView.getScrollX();
-
- @Override
- protected boolean check() {
- if (mScrollView.getScrollX() == mPreviousScrollX) {
- return true;
- } else {
- mPreviousScrollX = mScrollView.getScrollX();
- return false;
- }
+ final int[] previousScrollX = new int[] { mScrollView.getScrollX() };
+ PollingCheck.waitFor(() -> {
+ if (mScrollView.getScrollX() == previousScrollX[0]) {
+ return true;
+ } else {
+ previousScrollX[0] = mScrollView.getScrollX();
+ return false;
}
- }.run();
+ });
}
public static class MyView extends View {
diff --git a/tests/tests/widget/src/android/widget/cts/ImageButtonCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ImageButtonCtsActivity.java
new file mode 100644
index 0000000..5f91950
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ImageButtonCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.ImageButton;
+
+/**
+ * A minimal application for {@link ImageButton} test.
+ */
+public class ImageButtonCtsActivity extends Activity {
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.imagebutton_layout);
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java b/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java
index 05c0e3f..485024b 100644
--- a/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java
@@ -16,27 +16,42 @@
package android.widget.cts;
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.test.AndroidTestCase;
-import android.util.AttributeSet;
-import android.util.Xml;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
import android.widget.ImageButton;
+import android.widget.cts.util.TestUtils;
-public class ImageButtonTest extends AndroidTestCase {
+@SmallTest
+public class ImageButtonTest extends ActivityInstrumentationTestCase2<ImageButtonCtsActivity> {
+ private Instrumentation mInstrumentation;
+ private Activity mActivity;
+ private ImageButton mImageButton;
+
+ public ImageButtonTest() {
+ super("android.widget.cts", ImageButtonCtsActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mInstrumentation = getInstrumentation();
+ mActivity = getActivity();
+ mImageButton = (ImageButton) mActivity.findViewById(R.id.image_button);
+ }
+
public void testConstructor() {
- XmlPullParser parser = getContext().getResources().getXml(R.layout.imagebutton_test);
- AttributeSet attrs = Xml.asAttributeSet(parser);
- assertNotNull(attrs);
-
- new ImageButton(getContext());
-
- new ImageButton(getContext(), attrs);
-
- new ImageButton(getContext(), attrs, 0);
+ new ImageButton(mActivity);
+ new ImageButton(mActivity, null);
+ new ImageButton(mActivity, null, android.R.attr.imageButtonStyle);
+ new ImageButton(mActivity, null, 0, android.R.style.Widget_DeviceDefault_ImageButton);
+ new ImageButton(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_ImageButton);
+ new ImageButton(mActivity, null, 0, android.R.style.Widget_Material_ImageButton);
+ new ImageButton(mActivity, null, 0, android.R.style.Widget_Material_Light_ImageButton);
try {
new ImageButton(null);
@@ -57,7 +72,23 @@
}
}
- public void testOnSetAlpha() {
- // Do not test, it's controlled by View. Implementation details.
+ public void testImageSource() {
+ Drawable imageButtonDrawable = mImageButton.getDrawable();
+ TestUtils.assertAllPixelsOfColor("Default source is red", imageButtonDrawable,
+ imageButtonDrawable.getIntrinsicWidth(), imageButtonDrawable.getIntrinsicHeight(),
+ true, Color.RED, 1, false);
+
+ mInstrumentation.runOnMainSync(() -> mImageButton.setImageResource(R.drawable.icon_green));
+ imageButtonDrawable = mImageButton.getDrawable();
+ TestUtils.assertAllPixelsOfColor("New source is green", imageButtonDrawable,
+ imageButtonDrawable.getIntrinsicWidth(), imageButtonDrawable.getIntrinsicHeight(),
+ true, Color.GREEN, 1, false);
+
+ mInstrumentation.runOnMainSync(
+ () -> mImageButton.setImageDrawable(mActivity.getDrawable(R.drawable.icon_yellow)));
+ imageButtonDrawable = mImageButton.getDrawable();
+ TestUtils.assertAllPixelsOfColor("New source is yellow", imageButtonDrawable,
+ imageButtonDrawable.getIntrinsicWidth(), imageButtonDrawable.getIntrinsicHeight(),
+ true, Color.YELLOW, 1, false);
}
}
diff --git a/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java b/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
index 4d0903a..24878ce 100644
--- a/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
@@ -16,15 +16,20 @@
package android.widget.cts;
-import org.xmlpull.v1.XmlPullParser;
-
+import android.annotation.ColorInt;
import android.app.Activity;
+import android.app.Instrumentation;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.test.ActivityInstrumentationTestCase;
import android.test.ViewAsserts;
+import android.test.suitebuilder.annotation.SmallTest;
import android.util.AttributeSet;
import android.util.Xml;
+import android.view.Gravity;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
@@ -34,7 +39,10 @@
import android.widget.LinearLayout.LayoutParams;
import android.widget.ListView;
import android.widget.TextView;
-import android.widget.cts.R;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
+
+import org.xmlpull.v1.XmlPullParser;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -42,6 +50,7 @@
/**
* Test {@link LinearLayout}.
*/
+@SmallTest
public class LinearLayoutTest extends ActivityInstrumentationTestCase<LinearLayoutCtsActivity> {
private Context mContext;
private Activity mActivity;
@@ -152,9 +161,9 @@
*/
public void testAccessWeightSum() {
LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.weightsum);
- TextView weight02 = (TextView) mActivity.findViewById(R.id.weight_0_2);
- TextView weight05 = (TextView) mActivity.findViewById(R.id.weight_0_5);
- TextView weight03 = (TextView) mActivity.findViewById(R.id.weight_0_3);
+ TextView weight02 = (TextView) parent.findViewById(R.id.weight_0_2);
+ TextView weight05 = (TextView) parent.findViewById(R.id.weight_0_5);
+ TextView weight03 = (TextView) parent.findViewById(R.id.weight_0_3);
assertNotNull(parent);
assertNotNull(weight02);
@@ -399,6 +408,182 @@
assertEquals(parent.getWidth(), rightView.getRight());
}
+ public void testVerticalCenterGravityOnHorizontalLayout() {
+ final Instrumentation instrumentation = getInstrumentation();
+ LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.weightsum);
+ TextView leftView = (TextView) parent.findViewById(R.id.weight_0_2);
+ TextView centerView = (TextView) parent.findViewById(R.id.weight_0_5);
+ TextView rightView = (TextView) parent.findViewById(R.id.weight_0_3);
+
+ instrumentation.runOnMainSync(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+ instrumentation.waitForIdleSync();
+
+ int originalLeftViewRight = leftView.getRight();
+ int originalCenterViewLeft = centerView.getLeft();
+ int originalCenterViewRight = centerView.getRight();
+ int originalRightViewLeft = rightView.getLeft();
+
+ instrumentation.runOnMainSync(() -> parent.setVerticalGravity(Gravity.CENTER_VERTICAL));
+ instrumentation.waitForIdleSync();
+
+ assertEquals(Gravity.CENTER_VERTICAL, parent.getGravity() & Gravity.VERTICAL_GRAVITY_MASK);
+
+ ViewAsserts.assertVerticalCenterAligned(parent, leftView);
+ ViewAsserts.assertVerticalCenterAligned(parent, centerView);
+ ViewAsserts.assertVerticalCenterAligned(parent, rightView);
+
+ final int parentHeight = parent.getHeight();
+
+ int verticalOffset = (parentHeight - leftView.getHeight()) / 2;
+ assertEquals(verticalOffset, leftView.getTop());
+ assertEquals(verticalOffset + leftView.getHeight(), leftView.getBottom());
+ assertEquals(0, leftView.getLeft());
+ assertEquals(originalLeftViewRight, leftView.getRight());
+
+ verticalOffset = (parentHeight - centerView.getHeight()) / 2;
+ assertEquals(verticalOffset, centerView.getTop());
+ assertEquals(verticalOffset + centerView.getHeight(), centerView.getBottom());
+ assertEquals(originalCenterViewLeft, centerView.getLeft());
+ assertEquals(originalCenterViewRight, centerView.getRight());
+
+ verticalOffset = (parentHeight - rightView.getHeight()) / 2;
+ assertEquals(verticalOffset, rightView.getTop());
+ assertEquals(verticalOffset + rightView.getHeight(), rightView.getBottom());
+ assertEquals(originalRightViewLeft, rightView.getLeft());
+ assertEquals(parent.getWidth(), rightView.getRight());
+ }
+
+ public void testBottomGravityOnHorizontalLayout() {
+ final Instrumentation instrumentation = getInstrumentation();
+ LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.weightsum);
+ TextView leftView = (TextView) parent.findViewById(R.id.weight_0_2);
+ TextView centerView = (TextView) parent.findViewById(R.id.weight_0_5);
+ TextView rightView = (TextView) parent.findViewById(R.id.weight_0_3);
+
+ instrumentation.runOnMainSync(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+ instrumentation.waitForIdleSync();
+
+ int originalLeftViewRight = leftView.getRight();
+ int originalCenterViewLeft = centerView.getLeft();
+ int originalCenterViewRight = centerView.getRight();
+ int originalRightViewLeft = rightView.getLeft();
+
+ instrumentation.runOnMainSync(() -> parent.setVerticalGravity(Gravity.BOTTOM));
+ instrumentation.waitForIdleSync();
+
+ assertEquals(Gravity.BOTTOM, parent.getGravity() & Gravity.VERTICAL_GRAVITY_MASK);
+
+ ViewAsserts.assertBottomAligned(parent, leftView);
+ ViewAsserts.assertBottomAligned(parent, centerView);
+ ViewAsserts.assertBottomAligned(parent, rightView);
+
+ final int parentHeight = parent.getHeight();
+
+ assertEquals(parentHeight - leftView.getHeight(), leftView.getTop());
+ assertEquals(parentHeight, leftView.getBottom());
+ assertEquals(0, leftView.getLeft());
+ assertEquals(originalLeftViewRight, leftView.getRight());
+
+ assertEquals(parentHeight - centerView.getHeight(), centerView.getTop());
+ assertEquals(parentHeight, centerView.getBottom());
+ assertEquals(originalCenterViewLeft, centerView.getLeft());
+ assertEquals(originalCenterViewRight, centerView.getRight());
+
+ assertEquals(parentHeight - rightView.getHeight(), rightView.getTop());
+ assertEquals(parentHeight, rightView.getBottom());
+ assertEquals(originalRightViewLeft, rightView.getLeft());
+ assertEquals(parent.getWidth(), rightView.getRight());
+ }
+
+ public void testHorizontalCenterGravityOnVerticalLayout() {
+ final Instrumentation instrumentation = getInstrumentation();
+ LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.weightsum_vertical);
+ TextView topView = (TextView) parent.findViewById(R.id.weight_0_1);
+ TextView centerView = (TextView) parent.findViewById(R.id.weight_0_4);
+ TextView bottomView = (TextView) parent.findViewById(R.id.weight_0_5);
+
+ instrumentation.runOnMainSync(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+ instrumentation.waitForIdleSync();
+
+ final int parentWidth = parent.getHeight();
+
+ int originalTopViewBottom = topView.getBottom();
+ int originalCenterViewTop = centerView.getTop();
+ int originalCenterViewBottom = centerView.getBottom();
+ int originalBottomViewTop = bottomView.getTop();
+
+ instrumentation.runOnMainSync(() -> parent.setHorizontalGravity(Gravity.CENTER_HORIZONTAL));
+ instrumentation.waitForIdleSync();
+
+ assertEquals(Gravity.CENTER_HORIZONTAL,
+ parent.getGravity() & Gravity.HORIZONTAL_GRAVITY_MASK);
+
+ ViewAsserts.assertHorizontalCenterAligned(parent, topView);
+ ViewAsserts.assertHorizontalCenterAligned(parent, centerView);
+ ViewAsserts.assertHorizontalCenterAligned(parent, bottomView);
+
+ int horizontalOffset = (parentWidth - topView.getWidth()) / 2;
+ assertEquals(0, topView.getTop());
+ assertEquals(originalTopViewBottom, topView.getBottom());
+ assertEquals(horizontalOffset, topView.getLeft());
+ assertEquals(horizontalOffset + topView.getWidth(), topView.getRight());
+
+ horizontalOffset = (parentWidth - centerView.getWidth()) / 2;
+ assertEquals(originalCenterViewTop, centerView.getTop());
+ assertEquals(originalCenterViewBottom, centerView.getBottom());
+ assertEquals(horizontalOffset, centerView.getLeft());
+ assertEquals(horizontalOffset + centerView.getWidth(), centerView.getRight());
+
+ horizontalOffset = (parentWidth - bottomView.getWidth()) / 2;
+ assertEquals(originalBottomViewTop, bottomView.getTop());
+ assertEquals(parent.getHeight(), bottomView.getBottom());
+ assertEquals(horizontalOffset, bottomView.getLeft());
+ assertEquals(horizontalOffset + bottomView.getWidth(), bottomView.getRight());
+ }
+
+ public void testRightGravityOnVerticalLayout() {
+ final Instrumentation instrumentation = getInstrumentation();
+ LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.weightsum_vertical);
+ TextView topView = (TextView) parent.findViewById(R.id.weight_0_1);
+ TextView centerView = (TextView) parent.findViewById(R.id.weight_0_4);
+ TextView bottomView = (TextView) parent.findViewById(R.id.weight_0_5);
+
+ instrumentation.runOnMainSync(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+ instrumentation.waitForIdleSync();
+
+ final int parentWidth = parent.getHeight();
+
+ int originalTopViewBottom = topView.getBottom();
+ int originalCenterViewTop = centerView.getTop();
+ int originalCenterViewBottom = centerView.getBottom();
+ int originalBottomViewTop = bottomView.getTop();
+
+ instrumentation.runOnMainSync(() -> parent.setHorizontalGravity(Gravity.RIGHT));
+ instrumentation.waitForIdleSync();
+
+ assertEquals(Gravity.RIGHT,
+ parent.getGravity() & Gravity.HORIZONTAL_GRAVITY_MASK);
+
+ ViewAsserts.assertRightAligned(parent, topView);
+ ViewAsserts.assertRightAligned(parent, centerView);
+ ViewAsserts.assertRightAligned(parent, bottomView);
+
+ assertEquals(0, topView.getTop());
+ assertEquals(originalTopViewBottom, topView.getBottom());
+ assertEquals(parentWidth - topView.getWidth(), topView.getLeft());
+ assertEquals(parentWidth, topView.getRight());
+
+ assertEquals(originalCenterViewTop, centerView.getTop());
+ assertEquals(originalCenterViewBottom, centerView.getBottom());
+ assertEquals(parentWidth - centerView.getWidth(), centerView.getLeft());
+ assertEquals(parentWidth, centerView.getRight());
+
+ assertEquals(originalBottomViewTop, bottomView.getTop());
+ assertEquals(parent.getHeight(), bottomView.getBottom());
+ assertEquals(parentWidth - bottomView.getWidth(), bottomView.getLeft());
+ assertEquals(parentWidth, bottomView.getRight());
+ }
+
private void checkBounds(final ViewGroup viewGroup, final View view,
final CountDownLatch countDownLatch, final int left, final int top,
final int width, final int height) {
@@ -471,6 +656,523 @@
countDownLatch3.await(500, TimeUnit.MILLISECONDS);
}
+ private void verifyVisualsOfVerticalLayoutWithDivider(LinearLayout parent,
+ int expectedDividerPositionMask,
+ int expectedDividerSize, @ColorInt int expectedDividerColor,
+ int expectedDividerPadding) {
+ final int parentWidth = parent.getWidth();
+ final int parentHeight = parent.getHeight();
+
+ final boolean expectingTopDivider =
+ (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_BEGINNING) != 0;
+ final boolean expectingMiddleDivider =
+ (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_MIDDLE) != 0;
+ final boolean expectingBottomDivider =
+ (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_END) != 0;
+ final int expectedDividerCount = (expectingTopDivider ? 1 : 0)
+ + (expectingMiddleDivider ? 1 : 0) + (expectingBottomDivider ? 1 : 0);
+
+ final int expectedChildHeight =
+ (parentHeight - expectedDividerCount * expectedDividerSize) / 2;
+
+ final int expectedTopChildTop = expectingTopDivider ? expectedDividerSize : 0;
+ TestUtils.assertRegionPixelsOfColor("Region of first child is blue", parent,
+ new Rect(0, expectedTopChildTop, parentWidth,
+ expectedTopChildTop + expectedChildHeight),
+ Color.BLUE, 1, true);
+
+ final int expectedBottomChildBottom =
+ expectingBottomDivider ? parentHeight - expectedDividerSize : parentHeight;
+ TestUtils.assertRegionPixelsOfColor("Region of second child is green", parent,
+ new Rect(0, expectedBottomChildBottom - expectedChildHeight, parentWidth,
+ expectedBottomChildBottom),
+ Color.GREEN, 1, true);
+
+ if (expectedDividerSize == 0) {
+ return;
+ }
+
+ // Do we expect top divider?
+ if (expectingTopDivider) {
+ TestUtils.assertRegionPixelsOfColor(
+ "Region of top divider is " + TestUtils.formatColorToHex(expectedDividerColor),
+ parent,
+ new Rect(expectedDividerPadding, 0, parentWidth - expectedDividerPadding,
+ expectedDividerSize),
+ expectedDividerColor, 1, true);
+ TestUtils.assertRegionPixelsOfColor("Region of left padding of top divider is yellow",
+ parent,
+ new Rect(0, 0, expectedDividerPadding, expectedDividerSize),
+ Color.YELLOW, 1, true);
+ TestUtils.assertRegionPixelsOfColor("Region of right padding of top divider is yellow",
+ parent,
+ new Rect(parentWidth - expectedDividerPadding, 0, parentWidth,
+ expectedDividerSize),
+ Color.YELLOW, 1, true);
+ }
+
+ // Do we expect middle divider?
+ if (expectingMiddleDivider) {
+ final int expectedMiddleDividerTop = expectedTopChildTop + expectedChildHeight;
+ TestUtils.assertRegionPixelsOfColor(
+ "Region of middle divider is " +
+ TestUtils.formatColorToHex(expectedDividerColor),
+ parent,
+ new Rect(expectedDividerPadding, expectedMiddleDividerTop,
+ parentWidth - expectedDividerPadding,
+ expectedMiddleDividerTop + expectedDividerSize),
+ expectedDividerColor, 1, true);
+ TestUtils.assertRegionPixelsOfColor(
+ "Region of left padding of middle divider is yellow",
+ parent,
+ new Rect(0, expectedMiddleDividerTop, expectedDividerPadding,
+ expectedMiddleDividerTop + expectedDividerSize),
+ Color.YELLOW, 1, true);
+ TestUtils.assertRegionPixelsOfColor(
+ "Region of right padding of middle divider is yellow",
+ parent,
+ new Rect(parentWidth - expectedDividerPadding, expectedMiddleDividerTop,
+ parentWidth, expectedMiddleDividerTop + expectedDividerSize),
+ Color.YELLOW, 1, true);
+ }
+
+ // Do we expect bottom divider?
+ if (expectingBottomDivider) {
+ final int expectedBottomDividerTop = expectedBottomChildBottom;
+ TestUtils.assertRegionPixelsOfColor(
+ "Region of bottom divider is " +
+ TestUtils.formatColorToHex(expectedDividerColor),
+ parent,
+ new Rect(expectedDividerPadding, expectedBottomDividerTop,
+ parentWidth - expectedDividerPadding,
+ expectedBottomDividerTop + expectedDividerSize),
+ expectedDividerColor, 1, true);
+ TestUtils.assertRegionPixelsOfColor(
+ "Region of left padding of bottom divider is yellow",
+ parent,
+ new Rect(0, expectedBottomDividerTop, expectedDividerPadding,
+ expectedBottomDividerTop + expectedDividerSize),
+ Color.YELLOW, 1, true);
+ TestUtils.assertRegionPixelsOfColor(
+ "Region of right padding of bottom divider is yellow",
+ parent,
+ new Rect(parentWidth - expectedDividerPadding, expectedBottomDividerTop,
+ parentWidth, expectedBottomDividerTop + expectedDividerSize),
+ Color.YELLOW, 1, true);
+ }
+ }
+
+ /**
+ * layout of vertical LinearLayout.
+ * -----------------------------------
+ * | ------------------------------- |
+ * | | child1 | |
+ * | ------------------------------- |
+ * | - - - - - - divider - - - - - - |
+ * | ------------------------------- |
+ * | | child2 | |
+ * | ------------------------------- |
+ * -----------------------------------
+ *
+ * Parent is filled with yellow color. Child 1 is filled with green and child 2 is filled
+ * with blue. Divider is red at the beginning. Throughout this method we reconfigure the
+ * visibility, drawable and paddings of the divider and verify the overall visuals of the
+ * container.
+ */
+ public void testDividersInVerticalLayout() {
+ final LinearLayout parent =
+ (LinearLayout) mActivity.findViewById(R.id.vertical_with_divider);
+
+ final Instrumentation instrumentation = getInstrumentation();
+
+ final Resources res = mActivity.getResources();
+ final int dividerSize = res.getDimensionPixelSize(R.dimen.linear_layout_divider_size);
+ final int dividerPadding = res.getDimensionPixelSize(R.dimen.linear_layout_divider_padding);
+
+ assertEquals(LinearLayout.SHOW_DIVIDER_MIDDLE, parent.getShowDividers());
+ assertEquals(dividerPadding, parent.getDividerPadding());
+ final Drawable dividerDrawable = parent.getDividerDrawable();
+ TestUtils.assertAllPixelsOfColor("Divider is red", dividerDrawable,
+ dividerDrawable.getIntrinsicWidth(), dividerDrawable.getIntrinsicHeight(),
+ false, Color.RED, 1, true);
+
+ // Test the initial visuals of the entire parent
+ verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+ dividerSize, Color.RED, dividerPadding);
+
+ // Change the divider to magenta
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setDividerDrawable(
+ mActivity.getDrawable(R.drawable.linear_layout_divider_magenta)));
+ verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+ dividerSize, Color.MAGENTA, dividerPadding);
+
+ // Change the divider to null (no divider effectively)
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setDividerDrawable(null));
+ verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+ 0, Color.TRANSPARENT, 0);
+
+ // Change the divider back to red
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setDividerDrawable(
+ mActivity.getDrawable(R.drawable.linear_layout_divider_red)));
+ verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+ dividerSize, Color.RED, dividerPadding);
+
+ // Change the padding to half the original size
+ final int halfPadding = dividerPadding / 2;
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setDividerPadding(halfPadding));
+ assertEquals(halfPadding, parent.getDividerPadding());
+ verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+ dividerSize, Color.RED, halfPadding);
+
+ // Change the padding to twice the original size
+ final int doublePadding = dividerPadding * 2;
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setDividerPadding(doublePadding));
+ assertEquals(doublePadding, parent.getDividerPadding());
+ verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+ dividerSize, Color.RED, doublePadding);
+
+ // And back to the original padding
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setDividerPadding(dividerPadding));
+ assertEquals(dividerPadding, parent.getDividerPadding());
+ verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+ dividerSize, Color.RED, dividerPadding);
+
+ // Set show dividers to NONE (no divider effectively)
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_NONE));
+ assertEquals(LinearLayout.SHOW_DIVIDER_NONE, parent.getShowDividers());
+ verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_NONE,
+ 0, Color.TRANSPARENT, 0);
+
+ // Show only top divider
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_BEGINNING));
+ assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING, parent.getShowDividers());
+ verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_BEGINNING,
+ dividerSize, Color.RED, dividerPadding);
+
+ // Show only bottom divider
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_END));
+ assertEquals(LinearLayout.SHOW_DIVIDER_END, parent.getShowDividers());
+ verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_END,
+ dividerSize, Color.RED, dividerPadding);
+
+ // Show top and bottom dividers
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setShowDividers(
+ LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END));
+ assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END,
+ parent.getShowDividers());
+ verifyVisualsOfVerticalLayoutWithDivider(parent,
+ LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END,
+ dividerSize, Color.RED, dividerPadding);
+
+ // Show top and middle dividers
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setShowDividers(
+ LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE));
+ assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE,
+ parent.getShowDividers());
+ verifyVisualsOfVerticalLayoutWithDivider(parent,
+ LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE,
+ dividerSize, Color.RED, dividerPadding);
+
+ // Show middle and bottom dividers
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setShowDividers(
+ LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END));
+ assertEquals(LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END,
+ parent.getShowDividers());
+ verifyVisualsOfVerticalLayoutWithDivider(parent,
+ LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END,
+ dividerSize, Color.RED, dividerPadding);
+
+ // Show top, middle and bottom dividers
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setShowDividers(
+ LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+ | LinearLayout.SHOW_DIVIDER_END));
+ assertEquals(
+ LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+ | LinearLayout.SHOW_DIVIDER_END,
+ parent.getShowDividers());
+ verifyVisualsOfVerticalLayoutWithDivider(parent,
+ LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+ | LinearLayout.SHOW_DIVIDER_END,
+ dividerSize, Color.RED, dividerPadding);
+ }
+
+ private void verifyVisualsOfHorizontalLayoutWithDivider(LinearLayout parent,
+ int expectedDividerPositionMask,
+ int expectedDividerSize, @ColorInt int expectedDividerColor,
+ int expectedDividerPadding) {
+ final int parentWidth = parent.getWidth();
+ final int parentHeight = parent.getHeight();
+
+ final boolean expectingLeftDivider =
+ (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_BEGINNING) != 0;
+ final boolean expectingMiddleDivider =
+ (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_MIDDLE) != 0;
+ final boolean expectingRightDivider =
+ (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_END) != 0;
+ final int expectedDividerCount = (expectingLeftDivider ? 1 : 0)
+ + (expectingMiddleDivider ? 1 : 0) + (expectingRightDivider ? 1 : 0);
+
+ final int expectedChildWidth =
+ (parentWidth - expectedDividerCount * expectedDividerSize) / 2;
+
+ final int expectedLeftChildLeft = expectingLeftDivider ? expectedDividerSize : 0;
+ TestUtils.assertRegionPixelsOfColor("Region of first child is blue", parent,
+ new Rect(expectedLeftChildLeft, 0,
+ expectedLeftChildLeft + expectedChildWidth, parentHeight),
+ Color.BLUE, 1, true);
+
+ final int expectedRightChildRight =
+ expectingRightDivider ? parentWidth - expectedDividerSize : parentWidth;
+ TestUtils.assertRegionPixelsOfColor("Region of second child is green", parent,
+ new Rect(expectedRightChildRight - expectedChildWidth, 0, expectedRightChildRight,
+ parentHeight),
+ Color.GREEN, 1, true);
+
+ if (expectedDividerSize == 0) {
+ return;
+ }
+
+ // Do we expect left divider?
+ if (expectingLeftDivider) {
+ TestUtils.assertRegionPixelsOfColor(
+ "Region of left divider is " + TestUtils.formatColorToHex(expectedDividerColor),
+ parent,
+ new Rect(0, expectedDividerPadding, expectedDividerSize,
+ parentHeight - expectedDividerPadding),
+ expectedDividerColor, 1, true);
+ TestUtils.assertRegionPixelsOfColor(
+ "Region of top padding of left divider is yellow",
+ parent,
+ new Rect(0, 0, expectedDividerSize, expectedDividerPadding),
+ Color.YELLOW, 1, true);
+ TestUtils.assertRegionPixelsOfColor(
+ "Region of bottom padding of left divider is yellow",
+ parent,
+ new Rect(0, parentHeight - expectedDividerPadding, expectedDividerSize,
+ parentHeight),
+ Color.YELLOW, 1, true);
+ }
+
+ // Do we expect middle divider?
+ if (expectingMiddleDivider) {
+ final int expectedMiddleDividerLeft = expectedLeftChildLeft + expectedChildWidth;
+ TestUtils.assertRegionPixelsOfColor(
+ "Region of middle divider is " +
+ TestUtils.formatColorToHex(expectedDividerColor),
+ parent,
+ new Rect(expectedMiddleDividerLeft, expectedDividerPadding,
+ expectedMiddleDividerLeft + expectedDividerSize,
+ parentHeight - expectedDividerPadding),
+ expectedDividerColor, 1, true);
+ TestUtils.assertRegionPixelsOfColor(
+ "Region of top padding of middle divider is yellow",
+ parent,
+ new Rect(expectedMiddleDividerLeft, 0,
+ expectedMiddleDividerLeft + expectedDividerSize,
+ expectedDividerPadding),
+ Color.YELLOW, 1, true);
+ TestUtils.assertRegionPixelsOfColor(
+ "Region of bottom padding of middle divider is yellow",
+ parent,
+ new Rect(expectedMiddleDividerLeft, parentHeight - expectedDividerPadding,
+ expectedMiddleDividerLeft + expectedDividerSize, parentHeight),
+ Color.YELLOW, 1, true);
+ }
+
+ // Do we expect right divider?
+ if (expectingRightDivider) {
+ final int expectedRightDividerLeft = expectedRightChildRight;
+ TestUtils.assertRegionPixelsOfColor(
+ "Region of right divider is " +
+ TestUtils.formatColorToHex(expectedDividerColor),
+ parent,
+ new Rect(expectedRightDividerLeft, expectedDividerPadding,
+ expectedRightDividerLeft + expectedDividerSize,
+ parentHeight - expectedDividerPadding),
+ expectedDividerColor, 1, true);
+ TestUtils.assertRegionPixelsOfColor(
+ "Region of top padding of right divider is yellow",
+ parent,
+ new Rect(expectedRightDividerLeft, 0,
+ expectedRightDividerLeft + expectedDividerSize,
+ expectedDividerPadding),
+ Color.YELLOW, 1, true);
+ TestUtils.assertRegionPixelsOfColor(
+ "Region of bottom padding of right divider is yellow",
+ parent,
+ new Rect(expectedRightDividerLeft, parentHeight - expectedDividerPadding,
+ expectedRightDividerLeft + expectedDividerSize, parentHeight),
+ Color.YELLOW, 1, true);
+ }
+ }
+
+ /**
+ * layout of horizontal LinearLayout.
+ * -----------------------------------
+ * | ------------ | ------------- |
+ * | | | | | |
+ * | | | d | | |
+ * | | | i | | |
+ * | | | v | | |
+ * | | child1 | i | child2 | |
+ * | | | d | | |
+ * | | | e | | |
+ * | | | r | | |
+ * | | | | | |
+ * | ------------ | ------------- |
+ * -----------------------------------
+ *
+ * Parent is filled with yellow color. Child 1 is filled with green and child 2 is filled
+ * with blue. Divider is red at the beginning. Throughout this method we reconfigure the
+ * visibility, drawable and paddings of the divider and verify the overall visuals of the
+ * container.
+ */
+ public void testDividersInHorizontalLayout() {
+ final LinearLayout parent =
+ (LinearLayout) mActivity.findViewById(R.id.horizontal_with_divider);
+
+ final Instrumentation instrumentation = getInstrumentation();
+
+ instrumentation.runOnMainSync(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+ instrumentation.waitForIdleSync();
+
+ final Resources res = mActivity.getResources();
+ final int dividerSize = res.getDimensionPixelSize(R.dimen.linear_layout_divider_size);
+ final int dividerPadding = res.getDimensionPixelSize(R.dimen.linear_layout_divider_padding);
+
+ assertEquals(LinearLayout.SHOW_DIVIDER_MIDDLE, parent.getShowDividers());
+ assertEquals(dividerPadding, parent.getDividerPadding());
+ final Drawable dividerDrawable = parent.getDividerDrawable();
+ TestUtils.assertAllPixelsOfColor("Divider is red", dividerDrawable,
+ dividerDrawable.getIntrinsicWidth(), dividerDrawable.getIntrinsicHeight(),
+ false, Color.RED, 1, true);
+
+ // Test the initial visuals of the entire parent
+ verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+ dividerSize, Color.RED, dividerPadding);
+
+ // Change the divider to magenta
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setDividerDrawable(
+ mActivity.getDrawable(R.drawable.linear_layout_divider_magenta)));
+ verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+ dividerSize, Color.MAGENTA, dividerPadding);
+
+ // Change the divider to null (no divider effectively)
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setDividerDrawable(null));
+ verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+ 0, Color.TRANSPARENT, 0);
+
+ // Change the divider back to red
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setDividerDrawable(
+ mActivity.getDrawable(R.drawable.linear_layout_divider_red)));
+ verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+ dividerSize, Color.RED, dividerPadding);
+
+ // Change the padding to half the original size
+ final int halfPadding = dividerPadding / 2;
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setDividerPadding(halfPadding));
+ assertEquals(halfPadding, parent.getDividerPadding());
+ verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+ dividerSize, Color.RED, halfPadding);
+
+ // Change the padding to twice the original size
+ final int doublePadding = dividerPadding * 2;
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setDividerPadding(doublePadding));
+ assertEquals(doublePadding, parent.getDividerPadding());
+ verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+ dividerSize, Color.RED, doublePadding);
+
+ // And back to the original padding
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setDividerPadding(dividerPadding));
+ assertEquals(dividerPadding, parent.getDividerPadding());
+ verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE,
+ dividerSize, Color.RED, dividerPadding);
+
+ // Set show dividers to NONE (no divider effectively)
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_NONE));
+ assertEquals(LinearLayout.SHOW_DIVIDER_NONE, parent.getShowDividers());
+ verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_NONE,
+ 0, Color.TRANSPARENT, 0);
+
+ // Show only left divider
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_BEGINNING));
+ assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING, parent.getShowDividers());
+ verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_BEGINNING,
+ dividerSize, Color.RED, dividerPadding);
+
+ // Show only right divider
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_END));
+ assertEquals(LinearLayout.SHOW_DIVIDER_END, parent.getShowDividers());
+ verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_END,
+ dividerSize, Color.RED, dividerPadding);
+
+ // Show left and right dividers
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setShowDividers(
+ LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END));
+ assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END,
+ parent.getShowDividers());
+ verifyVisualsOfHorizontalLayoutWithDivider(parent,
+ LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END,
+ dividerSize, Color.RED, dividerPadding);
+
+ // Show left and middle dividers
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setShowDividers(
+ LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE));
+ assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE,
+ parent.getShowDividers());
+ verifyVisualsOfHorizontalLayoutWithDivider(parent,
+ LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE,
+ dividerSize, Color.RED, dividerPadding);
+
+ // Show middle and right dividers
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setShowDividers(
+ LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END));
+ assertEquals(LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END,
+ parent.getShowDividers());
+ verifyVisualsOfHorizontalLayoutWithDivider(parent,
+ LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END,
+ dividerSize, Color.RED, dividerPadding);
+
+ // Show left, middle and right dividers
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, parent,
+ () -> parent.setShowDividers(
+ LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+ | LinearLayout.SHOW_DIVIDER_END));
+ assertEquals(
+ LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+ | LinearLayout.SHOW_DIVIDER_END,
+ parent.getShowDividers());
+ verifyVisualsOfHorizontalLayoutWithDivider(parent,
+ LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE
+ | LinearLayout.SHOW_DIVIDER_END,
+ dividerSize, Color.RED, dividerPadding);
+ }
+
private class MockListView extends ListView {
private final static int DEFAULT_CHILD_BASE_LINE = 1;
diff --git a/tests/tests/widget/src/android/widget/cts/LinearLayout_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/LinearLayout_LayoutParamsTest.java
index 4f36e94..8773247 100644
--- a/tests/tests/widget/src/android/widget/cts/LinearLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/LinearLayout_LayoutParamsTest.java
@@ -16,16 +16,14 @@
package android.widget.cts;
-import android.widget.cts.R;
-
-import org.xmlpull.v1.XmlPullParserException;
-
import android.content.res.XmlResourceParser;
import android.test.AndroidTestCase;
+import android.view.Gravity;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.LinearLayout;
import android.widget.cts.util.XmlUtils;
+import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
@@ -34,17 +32,47 @@
XmlResourceParser p = mContext.getResources().getLayout(R.layout.linearlayout_layout);
XmlUtils.beginDocument(p, "LinearLayout");
- new LinearLayout.LayoutParams(getContext(), p);
+ LinearLayout.LayoutParams linearLayoutParams =
+ new LinearLayout.LayoutParams(getContext(), p);
+ assertEquals(LayoutParams.MATCH_PARENT, linearLayoutParams.width);
+ assertEquals(LayoutParams.WRAP_CONTENT, linearLayoutParams.height);
+ assertEquals(0.0f, linearLayoutParams.weight);
+ assertEquals(-1, linearLayoutParams.gravity);
- new LinearLayout.LayoutParams(320, 240);
+ linearLayoutParams = new LinearLayout.LayoutParams(320, 240);
+ assertEquals(320, linearLayoutParams.width);
+ assertEquals(240, linearLayoutParams.height);
+ assertEquals(0.0f, linearLayoutParams.weight);
+ assertEquals(-1, linearLayoutParams.gravity);
- new LinearLayout.LayoutParams(320, 240, 0);
+ linearLayoutParams = new LinearLayout.LayoutParams(360, 320, 0.4f);
+ assertEquals(360, linearLayoutParams.width);
+ assertEquals(320, linearLayoutParams.height);
+ assertEquals(0.4f, linearLayoutParams.weight);
+ assertEquals(-1, linearLayoutParams.gravity);
- LayoutParams layoutParams = new LayoutParams(320, 480);
- new LinearLayout.LayoutParams(layoutParams);
+ LayoutParams layoutParams = new LayoutParams(200, 480);
+ linearLayoutParams = new LinearLayout.LayoutParams(layoutParams);
+ assertEquals(200, linearLayoutParams.width);
+ assertEquals(480, linearLayoutParams.height);
+ assertEquals(0.0f, linearLayoutParams.weight);
+ assertEquals(-1, linearLayoutParams.gravity);
- MarginLayoutParams marginLayoutParams = new MarginLayoutParams(320, 480);
- new LinearLayout.LayoutParams(marginLayoutParams);
+ MarginLayoutParams marginLayoutParams = new MarginLayoutParams(320, 200);
+ linearLayoutParams = new LinearLayout.LayoutParams(marginLayoutParams);
+ assertEquals(320, linearLayoutParams.width);
+ assertEquals(200, linearLayoutParams.height);
+ assertEquals(0.0f, linearLayoutParams.weight);
+ assertEquals(-1, linearLayoutParams.gravity);
+
+ LinearLayout.LayoutParams linearLayoutParams2 = new LinearLayout.LayoutParams(360, 720);
+ linearLayoutParams2.weight = 0.9f;
+ linearLayoutParams2.gravity = Gravity.RIGHT;
+ linearLayoutParams = new LinearLayout.LayoutParams(linearLayoutParams2);
+ assertEquals(360, linearLayoutParams.width);
+ assertEquals(720, linearLayoutParams.height);
+ assertEquals(0.9f, linearLayoutParams.weight);
+ assertEquals(Gravity.RIGHT, linearLayoutParams.gravity);
}
public void testDebug() {
diff --git a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
index b50f8c9..1564caf 100644
--- a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
@@ -105,7 +105,16 @@
new ListPopupWindow(mActivity, null, android.R.attr.popupWindowStyle);
+ new ListPopupWindow(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_ListPopupWindow);
+
+ new ListPopupWindow(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_Light_ListPopupWindow);
+
new ListPopupWindow(mActivity, null, 0, android.R.style.Widget_Material_ListPopupWindow);
+
+ new ListPopupWindow(mActivity, null, 0,
+ android.R.style.Widget_Material_Light_ListPopupWindow);
}
public void testNoDefaultVisibility() {
@@ -372,17 +381,6 @@
// Make sure that the modality of the popup window is set up correctly
assertEquals("Popup window modality", setupAsModal, mPopupWindow.isModal());
- // Determine the location of the popup on the screen so that we can emulate
- // a tap outside of its bounds to dismiss it
- final int[] popupOnScreenXY = new int[2];
- final Rect rect = new Rect();
- mPopupWindow.getListView().getLocationOnScreen(popupOnScreenXY);
- mPopupWindow.getBackground().getPadding(rect);
-
- int emulatedTapX = popupOnScreenXY[0] - rect.left - 20;
- int emulatedTapY = popupOnScreenXY[1] + mPopupWindow.getListView().getHeight() +
- rect.top + rect.bottom + 20;
-
// The logic below uses Instrumentation to emulate a tap outside the bounds of the
// displayed list popup window. This tap is then treated by the framework to be "split" as
// the ACTION_OUTSIDE for the popup itself, as well as DOWN / MOVE / UP for the underlying
@@ -392,29 +390,12 @@
// of Instrumentation is necessary here since Espresso's actions operate at the level
// of view or data. Also, we don't want to use View.dispatchTouchEvent directly as
// that would require emulation of two separate sequences as well.
-
- Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-
- // Inject DOWN event
- long downTime = SystemClock.uptimeMillis();
- MotionEvent eventDown = MotionEvent.obtain(
- downTime, downTime, MotionEvent.ACTION_DOWN, emulatedTapX, emulatedTapY, 1);
- instrumentation.sendPointerSync(eventDown);
-
- // Inject MOVE event
- long moveTime = SystemClock.uptimeMillis();
- MotionEvent eventMove = MotionEvent.obtain(
- moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedTapX, emulatedTapY, 1);
- instrumentation.sendPointerSync(eventMove);
-
- // Inject UP event
- long upTime = SystemClock.uptimeMillis();
- MotionEvent eventUp = MotionEvent.obtain(
- upTime, upTime, MotionEvent.ACTION_UP, emulatedTapX, emulatedTapY, 1);
- instrumentation.sendPointerSync(eventUp);
-
- // Wait for the system to process all events in the queue
- instrumentation.waitForIdleSync();
+ final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+ final ListView popupListView = mPopupWindow.getListView();
+ final Rect rect = new Rect();
+ mPopupWindow.getBackground().getPadding(rect);
+ ViewTestUtils.emulateTapOnScreen(instrumentation, popupListView,
+ -rect.left - 20, popupListView.getHeight() + rect.top + rect.bottom + 20);
// At this point our popup should not be showing and should have notified its
// dismiss listener
@@ -668,40 +649,6 @@
verifyNoMoreInteractions(mPopupWindowBuilder.mOnDismissListener);
}
- /**
- * Emulates a drag-down gestures by injecting ACTION events with {@link Instrumentation}.
- */
- private void emulateDragDownGesture(int emulatedX, int emulatedStartY, int swipeAmount) {
- // The logic below uses Instrumentation to emulate a swipe / drag gesture to bring up
- // the popup content.
-
- // Inject DOWN event
- long downTime = SystemClock.uptimeMillis();
- MotionEvent eventDown = MotionEvent.obtain(
- downTime, downTime, MotionEvent.ACTION_DOWN, emulatedX, emulatedStartY, 1);
- mInstrumentation.sendPointerSync(eventDown);
-
- // Inject a sequence of MOVE events that emulate a "swipe down" gesture
- for (int i = 0; i < 10; i++) {
- long moveTime = SystemClock.uptimeMillis();
- final int moveY = emulatedStartY + swipeAmount * i / 10;
- MotionEvent eventMove = MotionEvent.obtain(
- moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedX, moveY, 1);
- mInstrumentation.sendPointerSync(eventMove);
- // sleep for a bit to emulate a 200ms swipe
- SystemClock.sleep(20);
- }
-
- // Inject UP event
- long upTime = SystemClock.uptimeMillis();
- MotionEvent eventUp = MotionEvent.obtain(
- upTime, upTime, MotionEvent.ACTION_UP, emulatedX, emulatedStartY + swipeAmount, 1);
- mInstrumentation.sendPointerSync(eventUp);
-
- // Wait for the system to process all events in the queue
- mInstrumentation.waitForIdleSync();
- }
-
public void testCreateOnDragListener() throws Throwable {
// In this test we want precise control over the height of the popup content since
// we need to know by how much to swipe down to end the emulated gesture over the
@@ -738,7 +685,8 @@
int swipeAmount = 2 * popupRowHeight;
// Emulate drag-down gesture with a sequence of motion events
- emulateDragDownGesture(emulatedX, emulatedStartY, swipeAmount);
+ ViewTestUtils.emulateDragGesture(getInstrumentation(), emulatedX, emulatedStartY,
+ 0, swipeAmount);
// We expect the swipe / drag gesture to result in clicking the second item in our list.
verify(mPopupWindowBuilder.mOnItemClickListener, times(1)).onItemClick(
@@ -952,7 +900,8 @@
if (mHasItemSelectedListener) {
mOnItemSelectedListener = mock(AdapterView.OnItemSelectedListener.class);
mPopupWindow.setOnItemSelectedListener(mOnItemSelectedListener);
- mPopupWindow.setListSelector(mActivity.getDrawable(R.drawable.red_fill));
+ mPopupWindow.setListSelector(
+ mActivity.getDrawable(R.drawable.red_translucent_fill));
}
if (mHasDismissListener) {
diff --git a/tests/tests/widget/src/android/widget/cts/ListViewTest.java b/tests/tests/widget/src/android/widget/cts/ListViewTest.java
index e89b3d3..a0d2f57 100644
--- a/tests/tests/widget/src/android/widget/cts/ListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListViewTest.java
@@ -16,22 +16,21 @@
package android.widget.cts;
-import android.widget.BaseAdapter;
-import android.widget.LinearLayout;
-import android.widget.cts.R;
-
-import org.xmlpull.v1.XmlPullParser;
-
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.cts.util.PollingCheck;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.os.Parcelable;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
import android.util.AttributeSet;
import android.util.Pair;
import android.util.SparseBooleanArray;
@@ -40,25 +39,41 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LayoutAnimationController;
+import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
+import android.widget.cts.util.TestUtils;
import android.widget.cts.util.ViewTestUtils;
+import junit.framework.Assert;
+
+import org.xmlpull.v1.XmlPullParser;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-
-import junit.framework.Assert;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import static org.mockito.Mockito.*;
+@SmallTest
public class ListViewTest extends ActivityInstrumentationTestCase2<ListViewCtsActivity> {
private final String[] mCountryList = new String[] {
"Argentina", "Australia", "China", "France", "Germany", "Italy", "Japan", "United States"
};
+ private final String[] mLongCountryList = new String[] {
+ "Argentina", "Australia", "Belize", "Botswana", "Brazil", "Cameroon", "China", "Cyprus",
+ "Denmark", "Djibouti", "Ethiopia", "Fiji", "Finland", "France", "Gabon", "Germany",
+ "Ghana", "Haiti", "Honduras", "Iceland", "India", "Indonesia", "Ireland", "Italy",
+ "Japan", "Kiribati", "Laos", "Lesotho", "Liberia", "Malaysia", "Mongolia", "Myanmar",
+ "Nauru", "Norway", "Oman", "Pakistan", "Philippines", "Portugal", "Romania", "Russia",
+ "Rwanda", "Singapore", "Slovakia", "Slovenia", "Somalia", "Swaziland", "Togo", "Tuvalu",
+ "Uganda", "Ukraine", "United States", "Vanuatu", "Venezuela", "Zimbabwe"
+ };
private final String[] mNameList = new String[] {
"Jacky", "David", "Kevin", "Michael", "Andy"
};
@@ -69,6 +84,7 @@
private Instrumentation mInstrumentation;
private AttributeSet mAttributeSet;
private ArrayAdapter<String> mAdapter_countries;
+ private ArrayAdapter<String> mAdapter_longCountries;
private ArrayAdapter<String> mAdapter_names;
private ArrayAdapter<String> mAdapter_empty;
@@ -84,11 +100,13 @@
XmlPullParser parser = mActivity.getResources().getXml(R.layout.listview_layout);
mAttributeSet = Xml.asAttributeSet(parser);
- mAdapter_countries = new ArrayAdapter<String>(mActivity,
+ mAdapter_countries = new ArrayAdapter<>(mActivity,
android.R.layout.simple_list_item_1, mCountryList);
- mAdapter_names = new ArrayAdapter<String>(mActivity, android.R.layout.simple_list_item_1,
+ mAdapter_longCountries = new ArrayAdapter<>(mActivity,
+ android.R.layout.simple_list_item_1, mLongCountryList);
+ mAdapter_names = new ArrayAdapter<>(mActivity, android.R.layout.simple_list_item_1,
mNameList);
- mAdapter_empty = new ArrayAdapter<String>(mActivity, android.R.layout.simple_list_item_1,
+ mAdapter_empty = new ArrayAdapter<>(mActivity, android.R.layout.simple_list_item_1,
mEmptyList);
mListView = (ListView) mActivity.findViewById(R.id.listview_default);
@@ -142,12 +160,7 @@
Drawable d = mListView.getDivider();
final Rect r = d.getBounds();
- new PollingCheck() {
- @Override
- protected boolean check() {
- return r.bottom - r.top > 0;
- }
- }.run();
+ PollingCheck.waitFor(() -> r.bottom - r.top > 0);
ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
() -> mListView.setDividerHeight(20));
@@ -266,14 +279,18 @@
footerView2.setText("footerview2");
mInstrumentation.runOnMainSync(() -> mListView.setFooterDividersEnabled(true));
+ assertTrue(mListView.areFooterDividersEnabled());
assertEquals(0, mListView.getFooterViewsCount());
mInstrumentation.runOnMainSync(() -> mListView.addFooterView(footerView1, null, true));
+ assertTrue(mListView.areFooterDividersEnabled());
assertEquals(1, mListView.getFooterViewsCount());
- mInstrumentation.runOnMainSync(() -> mListView.addFooterView(footerView2));
-
- mInstrumentation.waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> {
+ mListView.setFooterDividersEnabled(false);
+ mListView.addFooterView(footerView2);
+ });
+ assertFalse(mListView.areFooterDividersEnabled());
assertEquals(2, mListView.getFooterViewsCount());
ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
@@ -281,10 +298,12 @@
ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
() -> mListView.removeFooterView(footerView1));
+ assertFalse(mListView.areFooterDividersEnabled());
assertEquals(1, mListView.getFooterViewsCount());
ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
() -> mListView.removeFooterView(footerView2));
+ assertFalse(mListView.areFooterDividersEnabled());
assertEquals(0, mListView.getFooterViewsCount());
}
@@ -293,18 +312,28 @@
final TextView headerView2 = (TextView) mActivity.findViewById(R.id.headerview2);
mInstrumentation.runOnMainSync(() -> mListView.setHeaderDividersEnabled(true));
+ assertTrue(mListView.areHeaderDividersEnabled());
assertEquals(0, mListView.getHeaderViewsCount());
mInstrumentation.runOnMainSync(() -> mListView.addHeaderView(headerView2, null, true));
+ assertTrue(mListView.areHeaderDividersEnabled());
assertEquals(1, mListView.getHeaderViewsCount());
- mInstrumentation.runOnMainSync(() -> mListView.addHeaderView(headerView1));
+ mInstrumentation.runOnMainSync(() -> {
+ mListView.setHeaderDividersEnabled(false);
+ mListView.addHeaderView(headerView1);
+ });
+ assertFalse(mListView.areHeaderDividersEnabled());
assertEquals(2, mListView.getHeaderViewsCount());
+
+ mInstrumentation.runOnMainSync(() -> mListView.removeHeaderView(headerView2));
+ assertFalse(mListView.areHeaderDividersEnabled());
+ assertEquals(1, mListView.getHeaderViewsCount());
}
public void testHeaderFooterType() throws Throwable {
final TextView headerView = new TextView(getActivity());
- final List<Pair<View, View>> mismatch = new ArrayList<Pair<View, View>>();
+ final List<Pair<View, View>> mismatch = new ArrayList<>();
final ArrayAdapter adapter = new ArrayAdapter<String>(mActivity,
android.R.layout.simple_list_item_1, mNameList) {
@Override
@@ -317,7 +346,7 @@
public View getView(int position, View convertView, ViewGroup parent) {
if (position == 0) {
if (convertView != null && convertView != headerView) {
- mismatch.add(new Pair<View, View>(headerView, convertView));
+ mismatch.add(new Pair<>(headerView, convertView));
}
return headerView;
} else {
@@ -345,12 +374,7 @@
Drawable defaultDrawable = mListView.getDivider();
final Rect r = defaultDrawable.getBounds();
- new PollingCheck() {
- @Override
- protected boolean check() {
- return r.bottom - r.top > 0;
- }
- }.run();
+ PollingCheck.waitFor(() -> r.bottom - r.top > 0);
final Drawable d = mActivity.getResources().getDrawable(R.drawable.scenery);
@@ -418,8 +442,24 @@
verifyNoMoreInteractions(onClickListener);
}
- public void testSaveAndRestoreInstanceState() {
- // implementation details, do NOT test
+ public void testSaveAndRestoreInstanceState_positionIsRestored() {
+ ListView listView = new ListView(mActivity);
+ listView.setAdapter(mAdapter_countries);
+ assertEquals(0, listView.getSelectedItemPosition());
+
+ int positionToTest = mAdapter_countries.getCount() - 1;
+ listView.setSelection(positionToTest);
+ assertEquals(positionToTest, listView.getSelectedItemPosition());
+ Parcelable savedState = listView.onSaveInstanceState();
+
+ listView.setSelection(positionToTest - 1);
+ assertEquals(positionToTest - 1, listView.getSelectedItemPosition());
+
+ listView.onRestoreInstanceState(savedState);
+ int measureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY);
+ listView.measure(measureSpec,measureSpec);
+ listView.layout(0, 0, 100, 100);
+ assertEquals(positionToTest, listView.getSelectedItemPosition());
}
public void testDispatchKeyEvent() {
@@ -574,7 +614,7 @@
ListView listView = new ListView(mActivity);
List<String> items = new ArrayList<>();
items.add("hello");
- Adapter<String> adapter = new Adapter<String>(mActivity, 0, items);
+ Adapter<String> adapter = new Adapter<>(mActivity, 0, items);
listView.setAdapter(adapter);
int measureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY);
@@ -599,7 +639,7 @@
listView.addHeaderView(new View(mActivity), null, false);
List<String> items = new ArrayList<>();
items.add("hello");
- Adapter<String> adapter = new Adapter<String>(mActivity, 0, items);
+ Adapter<String> adapter = new Adapter<>(mActivity, 0, items);
listView.setAdapter(adapter);
listView.setSelection(1);
@@ -930,28 +970,27 @@
}
public void testTransientStateStableIds() throws Exception {
- final ListView listView = mListView;
- final ArrayList<String> items = new ArrayList<String>(Arrays.asList(mCountryList));
- final StableArrayAdapter<String> adapter = new StableArrayAdapter<String>(mActivity,
+ final ArrayList<String> items = new ArrayList<>(Arrays.asList(mCountryList));
+ final StableArrayAdapter<String> adapter = new StableArrayAdapter<>(mActivity,
android.R.layout.simple_list_item_1, items);
ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
- () -> listView.setAdapter(adapter));
+ () -> mListView.setAdapter(adapter));
final Object tag = new Object();
- final View oldItem = listView.getChildAt(2);
+ final View oldItem = mListView.getChildAt(2);
final CharSequence oldText = ((TextView) oldItem.findViewById(android.R.id.text1))
.getText();
oldItem.setHasTransientState(true);
oldItem.setTag(tag);
- ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, listView,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
() -> {
adapter.remove(adapter.getItem(0));
adapter.notifyDataSetChanged();
});
- final View newItem = listView.getChildAt(1);
+ final View newItem = mListView.getChildAt(1);
final CharSequence newText = ((TextView) newItem.findViewById(android.R.id.text1))
.getText();
@@ -975,4 +1014,132 @@
return true;
}
}
+
+ @LargeTest
+ public void testSmoothScrollByOffset() {
+ final int itemCount = mLongCountryList.length;
+
+ mActivity.runOnUiThread(() -> mListView.setAdapter(mAdapter_longCountries));
+ mInstrumentation.waitForIdleSync();
+
+ assertEquals(0, mListView.getFirstVisiblePosition());
+
+ // If we're on a really big display, we might be in a situation where the position
+ // we're going to scroll to is already visible. In that case the logic in the rest
+ // of this test will never fire off a listener callback and then fail the test.
+ final int positionToScrollTo = itemCount - 10;
+ final int lastVisiblePosition = mListView.getLastVisiblePosition();
+ if (positionToScrollTo <= lastVisiblePosition) {
+ return;
+ }
+
+ // Register a scroll listener on our ListView. The listener will notify our latch
+ // when the "target" item comes into view. If that never happens, the latch will
+ // time out and fail the test.
+ final CountDownLatch latch = new CountDownLatch(1);
+ mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+ }
+
+ @Override
+ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+ int totalItemCount) {
+ if ((positionToScrollTo >= firstVisibleItem) &&
+ (positionToScrollTo <= (firstVisibleItem + visibleItemCount))) {
+ latch.countDown();
+ }
+ }
+ });
+ int offset = positionToScrollTo - lastVisiblePosition;
+ mActivity.runOnUiThread(() -> mListView.smoothScrollByOffset(offset));
+
+ boolean result = false;
+ try {
+ result = latch.await(20, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ assertTrue("Timed out while waiting for the target view to be scrolled into view", result);
+ }
+
+ private static class PositionArrayAdapter<T> extends ArrayAdapter<T> {
+ public PositionArrayAdapter(Context context, int resource, List<T> objects) {
+ super(context, resource, objects);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+ }
+
+ public void testGetCheckItemIds() {
+ final ArrayList<String> items = new ArrayList<>(Arrays.asList(mCountryList));
+ final ArrayAdapter<String> adapter = new PositionArrayAdapter<>(mActivity,
+ android.R.layout.simple_list_item_1, items);
+
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
+ () -> mListView.setAdapter(adapter));
+
+ mInstrumentation.runOnMainSync(
+ () -> mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE));
+ assertTrue(mListView.getCheckItemIds().length == 0);
+
+ mInstrumentation.runOnMainSync(() -> mListView.setItemChecked(2, true));
+ TestUtils.assertIdentical(new long[] { 2 }, mListView.getCheckItemIds());
+
+ mInstrumentation.runOnMainSync(() -> mListView.setItemChecked(4, true));
+ TestUtils.assertIdentical(new long[] { 2, 4 }, mListView.getCheckItemIds());
+
+ mInstrumentation.runOnMainSync(() -> mListView.setItemChecked(2, false));
+ TestUtils.assertIdentical(new long[] { 4 }, mListView.getCheckItemIds());
+
+ mInstrumentation.runOnMainSync(() -> mListView.setItemChecked(4, false));
+ assertTrue(mListView.getCheckItemIds().length == 0);
+ }
+
+ public void testAccessOverscrollHeader() {
+ final Drawable overscrollHeaderDrawable = spy(new ColorDrawable(Color.YELLOW));
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView, () -> {
+ mListView.setAdapter(mAdapter_longCountries);
+ mListView.setOverscrollHeader(overscrollHeaderDrawable);
+ });
+
+ assertEquals(overscrollHeaderDrawable, mListView.getOverscrollHeader());
+ verify(overscrollHeaderDrawable, never()).draw(any(Canvas.class));
+
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
+ () -> mListView.setScrollY(-mListView.getHeight() / 2));
+
+ verify(overscrollHeaderDrawable, atLeastOnce()).draw(any(Canvas.class));
+ }
+
+ public void testAccessOverscrollFooter() {
+ final Drawable overscrollFooterDrawable = spy(new ColorDrawable(Color.MAGENTA));
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView, () -> {
+ // Configure ListView to automatically scroll to the selected item
+ mListView.setStackFromBottom(true);
+ mListView.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
+
+ mListView.setAdapter(mAdapter_longCountries);
+ mListView.setOverscrollFooter(overscrollFooterDrawable);
+
+ // Set selection to the last item
+ mListView.setSelection(mAdapter_longCountries.getCount() - 1);
+ });
+
+ assertEquals(overscrollFooterDrawable, mListView.getOverscrollFooter());
+ verify(overscrollFooterDrawable, never()).draw(any(Canvas.class));
+
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mListView,
+ () -> mListView.setScrollY(mListView.getHeight() / 2));
+
+ verify(overscrollFooterDrawable, atLeastOnce()).draw(any(Canvas.class));
+ }
}
diff --git a/tests/tests/widget/src/android/widget/cts/MediaControllerTest.java b/tests/tests/widget/src/android/widget/cts/MediaControllerTest.java
index 2c60a91..8e312ed 100644
--- a/tests/tests/widget/src/android/widget/cts/MediaControllerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/MediaControllerTest.java
@@ -16,11 +16,6 @@
package android.widget.cts;
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
@@ -31,14 +26,17 @@
import android.util.Xml;
import android.view.MotionEvent;
import android.view.View;
-import android.view.View.OnClickListener;
import android.widget.MediaController;
import android.widget.VideoView;
+import org.xmlpull.v1.XmlPullParser;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import static org.mockito.Mockito.mock;
+
/**
* Test {@link MediaController}.
*/
@@ -47,7 +45,6 @@
private MediaController mMediaController;
private Activity mActivity;
private Instrumentation mInstrumentation;
- private static final long DEFAULT_TIMEOUT = 3000;
public MediaControllerTest() {
super("android.widget.cts", MediaControllerCtsActivity.class);
@@ -151,12 +148,7 @@
assertTrue(mMediaController.isShowing());
// isShowing() should return false, but MediaController still shows, this may be a bug.
- new PollingCheck(timeout + 500) {
- @Override
- protected boolean check() {
- return mMediaController.isShowing();
- }
- }.run();
+ PollingCheck.waitFor(500, () -> mMediaController.isShowing());
}
private String prepareSampleVideo() {
@@ -236,9 +228,9 @@
mMediaController.setAnchorView(videoView);
mMediaController.setMediaPlayer(mediaPlayerControl);
- final MockOnClickListener next = new MockOnClickListener();
- final MockOnClickListener prev = new MockOnClickListener();
- mMediaController.setPrevNextListeners(next, prev);
+ final View.OnClickListener mockNextClickListener = mock(View.OnClickListener.class);
+ final View.OnClickListener mockPrevClickListener = mock(View.OnClickListener.class);
+ mMediaController.setPrevNextListeners(mockNextClickListener, mockPrevClickListener);
mMediaController.show();
@@ -258,9 +250,9 @@
mMediaController.setAnchorView(videoView);
mMediaController.setMediaPlayer(mediaPlayerControl);
- final MockOnClickListener next = new MockOnClickListener();
- final MockOnClickListener prev = new MockOnClickListener();
- mMediaController.setPrevNextListeners(next, prev);
+ final View.OnClickListener mockNextClickListener = mock(View.OnClickListener.class);
+ final View.OnClickListener mockPrevClickListener = mock(View.OnClickListener.class);
+ mMediaController.setPrevNextListeners(mockNextClickListener, mockPrevClickListener);
}
private static class MockMediaPlayerControl implements MediaController.MediaPlayerControl {
@@ -318,16 +310,4 @@
return 0;
}
}
-
- private static class MockOnClickListener implements OnClickListener {
- private boolean mOnClickCalled = false;
-
- public boolean hasOnClickCalled() {
- return mOnClickCalled;
- }
-
- public void onClick(View v) {
- mOnClickCalled = true;
- }
- }
}
diff --git a/tests/tests/widget/src/android/widget/cts/MockTextView.java b/tests/tests/widget/src/android/widget/cts/MockTextView.java
index 977e4b2..1bc80dc 100644
--- a/tests/tests/widget/src/android/widget/cts/MockTextView.java
+++ b/tests/tests/widget/src/android/widget/cts/MockTextView.java
@@ -36,6 +36,11 @@
private boolean mHasCalledOnWindowFocusChanged;
private boolean mHasCalledOnPrivateIMECommand;
private boolean mHasCalledOnKeyMultiple;
+ private boolean mHasCalledOnSelectionChanged;
+ private int mSelectionChangedStart;
+ private int mSelectionChangedEnd;
+ private boolean mHasCalledOnBeginBatchEdit;
+ private boolean mHasCalledOnEndBatchEdit;
public MockTextView(Context context) {
super(context);
@@ -81,6 +86,26 @@
return mHasCalledOnKeyMultiple;
}
+ public boolean hasCalledOnSelectionChanged() {
+ return mHasCalledOnSelectionChanged;
+ }
+
+ public boolean hasCalledOnBeginBatchEdit() {
+ return mHasCalledOnBeginBatchEdit;
+ }
+
+ public boolean hasCalledOnEndBatchEdit() {
+ return mHasCalledOnEndBatchEdit;
+ }
+
+ public int getSelectionChangedStart() {
+ return mSelectionChangedStart;
+ }
+
+ public int getSelectionChangedEnd() {
+ return mSelectionChangedEnd;
+ }
+
public void reset() {
mHasCalledOnWindowFocusChanged = false;
mHasCalledDrawableStateChanged = false;
@@ -90,6 +115,11 @@
mHasCalledOnTextChanged = false;
mHasCalledOnPrivateIMECommand = false;
mHasCalledOnKeyMultiple = false;
+ mHasCalledOnSelectionChanged = false;
+ mSelectionChangedStart = -1;
+ mSelectionChangedEnd = -1;
+ mHasCalledOnBeginBatchEdit = false;
+ mHasCalledOnEndBatchEdit = false;
}
public int computeHorizontalScrollRange() {
@@ -178,6 +208,14 @@
return super.onPrivateIMECommand(action, data);
}
+ @Override
+ protected void onSelectionChanged(int selStart, int selEnd) {
+ super.onSelectionChanged(selStart, selEnd);
+ mHasCalledOnSelectionChanged = true;
+ mSelectionChangedStart = selStart;
+ mSelectionChangedEnd = selEnd;
+ }
+
public int getFrameLeft() {
return getLeft();
}
@@ -221,4 +259,16 @@
public int computeVerticalScrollExtent() {
return super.computeVerticalScrollExtent();
}
+
+ @Override
+ public void onBeginBatchEdit() {
+ super.onBeginBatchEdit();
+ mHasCalledOnBeginBatchEdit = true;
+ }
+
+ @Override
+ public void onEndBatchEdit() {
+ super.onEndBatchEdit();
+ mHasCalledOnEndBatchEdit = true;
+ }
}
diff --git a/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java b/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java
index 5c18030..2792504 100644
--- a/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java
@@ -16,32 +16,35 @@
package android.widget.cts;
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
import android.app.Activity;
+import android.app.Instrumentation;
import android.content.Context;
import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Xml;
import android.view.KeyEvent;
import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
import android.widget.Filter;
import android.widget.MultiAutoCompleteTextView;
import android.widget.MultiAutoCompleteTextView.CommaTokenizer;
import android.widget.MultiAutoCompleteTextView.Tokenizer;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
-public class MultiAutoCompleteTextViewTest extends ActivityInstrumentationTestCase2
- <MultiAutoCompleteTextViewCtsActivity> {
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@MediumTest
+public class MultiAutoCompleteTextViewTest
+ extends ActivityInstrumentationTestCase2<MultiAutoCompleteTextViewCtsActivity> {
+ private Instrumentation mInstrumentation;
+ private Activity mActivity;
private MultiAutoCompleteTextView mMultiAutoCompleteTextView_country;
private MultiAutoCompleteTextView mMultiAutoCompleteTextView_name;
- private Activity mActivity;
public MultiAutoCompleteTextViewTest() {
super("android.widget.cts", MultiAutoCompleteTextViewCtsActivity.class);
@@ -51,23 +54,26 @@
protected void setUp() throws Exception {
super.setUp();
+ mInstrumentation = getInstrumentation();
mActivity = getActivity();
-
mMultiAutoCompleteTextView_country = (MultiAutoCompleteTextView)mActivity
.findViewById(R.id.country_edit);
mMultiAutoCompleteTextView_name = (MultiAutoCompleteTextView)mActivity
.findViewById(R.id.name_edit);
}
- @UiThreadTest
public void testConstructor() {
- XmlPullParser parser = mActivity.getResources()
- .getXml(R.layout.multi_auto_complete_text_view_layout);
- AttributeSet attr = Xml.asAttributeSet(parser);
-
new MultiAutoCompleteTextView(mActivity);
- new MultiAutoCompleteTextView(mActivity, attr);
- new MultiAutoCompleteTextView(mActivity, attr, 0);
+ new MultiAutoCompleteTextView(mActivity, null);
+ new MultiAutoCompleteTextView(mActivity, null, android.R.attr.autoCompleteTextViewStyle);
+ new MultiAutoCompleteTextView(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_AutoCompleteTextView);
+ new MultiAutoCompleteTextView(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_Light_AutoCompleteTextView);
+ new MultiAutoCompleteTextView(mActivity, null, 0,
+ android.R.style.Widget_Material_AutoCompleteTextView);
+ new MultiAutoCompleteTextView(mActivity, null, 0,
+ android.R.style.Widget_Material_Light_AutoCompleteTextView);
try {
new MultiAutoCompleteTextView(null);
@@ -91,19 +97,21 @@
}
}
- @UiThreadTest
- private void setText(MultiAutoCompleteTextView m, CharSequence c) {
- m.setText(c);
- m.setSelection(0, c.length());
+ private void setText(final MultiAutoCompleteTextView m, final CharSequence c) {
+ mInstrumentation.runOnMainSync(() -> {
+ m.setText(c);
+ m.setSelection(0, c.length());
+ });
}
- @UiThreadTest
public void testMultiAutoCompleteTextView() {
- mMultiAutoCompleteTextView_country.setTokenizer(new CommaTokenizer());
- mMultiAutoCompleteTextView_name.setTokenizer(new CommaTokenizer());
+ mInstrumentation.runOnMainSync(() -> {
+ mMultiAutoCompleteTextView_country.setTokenizer(new CommaTokenizer());
+ mMultiAutoCompleteTextView_name.setTokenizer(new CommaTokenizer());
- mMultiAutoCompleteTextView_country.setThreshold(3);
- mMultiAutoCompleteTextView_name.setThreshold(2);
+ mMultiAutoCompleteTextView_country.setThreshold(3);
+ mMultiAutoCompleteTextView_name.setThreshold(2);
+ });
assertFalse(mMultiAutoCompleteTextView_country.enoughToFilter());
assertFalse(mMultiAutoCompleteTextView_name.enoughToFilter());
@@ -125,76 +133,84 @@
setText(mMultiAutoCompleteTextView_name, "Jacky");
assertTrue(mMultiAutoCompleteTextView_name.enoughToFilter());
-
- MockValidator v = new MockValidator();
- v.setValid(true);
- mMultiAutoCompleteTextView_name.setValidator(v);
-
- // There will be an endless loop when using CommaTokenizer as the Tokenizer
- // mMultiAutoCompleteTextView_name.performValidation();
- mMultiAutoCompleteTextView_name.setValidator(null);
}
- @UiThreadTest
public void testPerformValidation() {
- MockValidator v = new MockValidator();
- v.setValid(true);
- mMultiAutoCompleteTextView_country.setValidator(v);
+ final AutoCompleteTextView.Validator validator = mock(AutoCompleteTextView.Validator.class);
+ when(validator.isValid(any(CharSequence.class))).thenReturn(true);
+ when(validator.fixText(any(CharSequence.class))).thenAnswer(
+ new Answer<CharSequence>() {
+ @Override
+ public CharSequence answer(InvocationOnMock invocation) throws Throwable {
+ // Return the originally passed parameter
+ return (CharSequence) invocation.getArguments()[0];
+ }
+ });
+
+ mInstrumentation.runOnMainSync(
+ () -> mMultiAutoCompleteTextView_country.setValidator(validator));
MockTokenizer t = new MockTokenizer();
- mMultiAutoCompleteTextView_country.setTokenizer(t);
+ mInstrumentation.runOnMainSync(() -> mMultiAutoCompleteTextView_country.setTokenizer(t));
String str = new String("Foo, Android Test, OH");
- mMultiAutoCompleteTextView_country.setText(str);
- mMultiAutoCompleteTextView_country.performValidation();
+ mInstrumentation.runOnMainSync(() -> {
+ mMultiAutoCompleteTextView_country.setText(str);
+ mMultiAutoCompleteTextView_country.performValidation();
+ });
assertEquals(str, mMultiAutoCompleteTextView_country.getText().toString());
- v.setValid(false);
- mMultiAutoCompleteTextView_country.performValidation();
+ when(validator.isValid(any(CharSequence.class))).thenReturn(false);
+ mInstrumentation.runOnMainSync(
+ () -> mMultiAutoCompleteTextView_country.performValidation());
assertEquals(str + ", ", mMultiAutoCompleteTextView_country.getText().toString());
}
- @UiThreadTest
public void testPerformFiltering() {
MyMultiAutoCompleteTextView multiAutoCompleteTextView =
new MyMultiAutoCompleteTextView(mActivity);
CommaTokenizer t = new CommaTokenizer();
- multiAutoCompleteTextView.setTokenizer(t);
+ mInstrumentation.runOnMainSync(() -> multiAutoCompleteTextView.setTokenizer(t));
ArrayAdapter<String> adapter = new ArrayAdapter<String>(mActivity,
R.layout.simple_dropdown_item_1line);
assertNotNull(adapter);
- multiAutoCompleteTextView.setAdapter(adapter);
+ mInstrumentation.runOnMainSync(() -> multiAutoCompleteTextView.setAdapter(adapter));
assertNotNull(multiAutoCompleteTextView.getFilter());
String text = "Android test.";
- multiAutoCompleteTextView.setText(text);
- multiAutoCompleteTextView.setSelection(0, 12);
+ mInstrumentation.runOnMainSync(() -> {
+ multiAutoCompleteTextView.setText(text);
+ multiAutoCompleteTextView.setSelection(0, 12);
+ multiAutoCompleteTextView.performFiltering(text, KeyEvent.KEYCODE_0);
+ });
- multiAutoCompleteTextView.performFiltering(text, KeyEvent.KEYCODE_0);
assertNotNull(multiAutoCompleteTextView.getFilter());
- multiAutoCompleteTextView.performFiltering(text, 0, text.length(), KeyEvent.KEYCODE_E);
+ mInstrumentation.runOnMainSync(
+ () -> multiAutoCompleteTextView.performFiltering(text, 0, text.length(),
+ KeyEvent.KEYCODE_E));
assertNotNull(multiAutoCompleteTextView.getFilter());
}
- @UiThreadTest
public void testReplaceText() {
MyMultiAutoCompleteTextView multiAutoCompleteTextView =
new MyMultiAutoCompleteTextView(mActivity);
CommaTokenizer t = new CommaTokenizer();
- multiAutoCompleteTextView.setTokenizer(t);
+ mInstrumentation.runOnMainSync(() -> multiAutoCompleteTextView.setTokenizer(t));
String text = "CTS.";
- multiAutoCompleteTextView.setText(text);
+ mInstrumentation.runOnMainSync(() -> multiAutoCompleteTextView.setText(text));
assertEquals(text, multiAutoCompleteTextView.getText().toString());
- multiAutoCompleteTextView.setSelection(0, text.length());
+ mInstrumentation.runOnMainSync(
+ () -> multiAutoCompleteTextView.setSelection(0, text.length()));
// set the selection range.
- multiAutoCompleteTextView.replaceText("Android Test.");
+ mInstrumentation.runOnMainSync(
+ () -> multiAutoCompleteTextView.replaceText("Android Test."));
assertEquals("Android Test., ", multiAutoCompleteTextView.getText().toString());
// do not set the selection range.
- multiAutoCompleteTextView.replaceText("replace test");
+ mInstrumentation.runOnMainSync(() -> multiAutoCompleteTextView.replaceText("replace test"));
assertEquals("Android Test., replace test, ",
multiAutoCompleteTextView.getText().toString());
}
@@ -253,22 +269,6 @@
}
}
- private class MockValidator implements MultiAutoCompleteTextView.Validator {
- private boolean mIsValid;
-
- public void setValid(boolean b) {
- mIsValid = b;
- }
-
- public boolean isValid(CharSequence text) {
- return mIsValid;
- }
-
- public CharSequence fixText(CharSequence invalidText) {
- return invalidText;
- }
- }
-
/**
* MyMultiAutoCompleteTextView
*/
diff --git a/tests/tests/widget/src/android/widget/cts/MyRemotableView.java b/tests/tests/widget/src/android/widget/cts/MyRemotableView.java
new file mode 100644
index 0000000..5452125
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/MyRemotableView.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.RemoteViews;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+@RemoteViews.RemoteView
+public class MyRemotableView extends TextView {
+ private byte mByteField;
+ private char mCharField;
+ private double mDoubleField;
+ private short mShortField;
+ private Bundle mBundleField;
+
+ public MyRemotableView(Context context) {
+ super(context);
+ }
+
+ public MyRemotableView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public MyRemotableView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @android.view.RemotableViewMethod
+ public void setByteField(byte value) {
+ mByteField = value;
+ }
+
+ public byte getByteField() {
+ return mByteField;
+ }
+
+ @android.view.RemotableViewMethod
+ public void setCharField(char value) {
+ mCharField = value;
+ }
+
+ public char getCharField() {
+ return mCharField;
+ }
+
+ @android.view.RemotableViewMethod
+ public void setDoubleField(double value) {
+ mDoubleField = value;
+ }
+
+ public double getDoubleField() {
+ return mDoubleField;
+ }
+
+ @android.view.RemotableViewMethod
+ public void setShortField(short value) {
+ mShortField = value;
+ }
+
+ public short getShortField() {
+ return mShortField;
+ }
+
+ @android.view.RemotableViewMethod
+ public void setBundleField(Bundle value) {
+ mBundleField = value;
+ }
+
+ public Bundle getBundleField() {
+ return mBundleField;
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/NumberPickerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/NumberPickerCtsActivity.java
new file mode 100644
index 0000000..f93a1da
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/NumberPickerCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.NumberPicker;
+
+/**
+ * A minimal application for {@link NumberPicker} test.
+ */
+public class NumberPickerCtsActivity extends Activity {
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.numberpicker_layout);
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java b/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java
new file mode 100644
index 0000000..cf69073
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ *
+ * 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.
+ */
+
+package android.widget.cts;
+
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
+import android.widget.NumberPicker;
+import android.widget.cts.util.ViewTestUtils;
+import org.mockito.InOrder;
+
+import static org.mockito.Mockito.*;
+
+@SmallTest
+public class NumberPickerTest extends ActivityInstrumentationTestCase2<NumberPickerCtsActivity> {
+ private static final String[] NUMBER_NAMES3 = {"One", "Two", "Three"};
+ private static final String[] NUMBER_NAMES_ALT3 = {"Three", "Four", "Five"};
+ private static final String[] NUMBER_NAMES5 = {"One", "Two", "Three", "Four", "Five"};
+
+ private Instrumentation mInstrumentation;
+ private NumberPickerCtsActivity mActivity;
+ private NumberPicker mNumberPicker;
+
+ public NumberPickerTest() {
+ super("android.widget.cts", NumberPickerCtsActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mInstrumentation = getInstrumentation();
+ mActivity = getActivity();
+ mNumberPicker = (NumberPicker) mActivity.findViewById(R.id.number_picker);
+ }
+
+ @UiThreadTest
+ public void testConstructor() {
+ new NumberPicker(mActivity);
+
+ new NumberPicker(mActivity, null);
+
+ new NumberPicker(mActivity, null, android.R.attr.numberPickerStyle);
+
+ new NumberPicker(mActivity, null, 0, android.R.style.Widget_Material_NumberPicker);
+
+ new NumberPicker(mActivity, null, 0, android.R.style.Widget_Material_Light_NumberPicker);
+ }
+
+ private void verifyDisplayedValues(String[] expected) {
+ final String[] displayedValues = mNumberPicker.getDisplayedValues();
+ assertEquals(expected.length, displayedValues.length);
+ for (int i = 0; i < expected.length; i++) {
+ assertEquals(expected[i], displayedValues[i]);
+ }
+ }
+
+ public void testSetDisplayedValuesRangeMatch() {
+ mInstrumentation.runOnMainSync(() -> {
+ mNumberPicker.setMinValue(10);
+ mNumberPicker.setMaxValue(12);
+ mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
+ });
+
+ assertEquals(10, mNumberPicker.getMinValue());
+ assertEquals(12, mNumberPicker.getMaxValue());
+ verifyDisplayedValues(NUMBER_NAMES3);
+
+ // Set a different displayed values array, but still matching the min/max range
+ mInstrumentation.runOnMainSync(() -> {
+ mNumberPicker.setDisplayedValues(NUMBER_NAMES_ALT3);
+ });
+
+ assertEquals(10, mNumberPicker.getMinValue());
+ assertEquals(12, mNumberPicker.getMaxValue());
+ verifyDisplayedValues(NUMBER_NAMES_ALT3);
+
+ mInstrumentation.runOnMainSync(() -> {
+ mNumberPicker.setMinValue(24);
+ mNumberPicker.setMaxValue(26);
+ });
+
+ assertEquals(24, mNumberPicker.getMinValue());
+ assertEquals(26, mNumberPicker.getMaxValue());
+ verifyDisplayedValues(NUMBER_NAMES_ALT3);
+ }
+
+ public void testSetDisplayedValuesRangeMismatch() {
+ mInstrumentation.runOnMainSync(() -> {
+ mNumberPicker.setMinValue(10);
+ mNumberPicker.setMaxValue(14);
+ });
+ assertEquals(10, mNumberPicker.getMinValue());
+ assertEquals(14, mNumberPicker.getMaxValue());
+
+ // Try setting too few displayed entries
+ mInstrumentation.runOnMainSync(() -> {
+ try {
+ // This is expected to fail since the displayed values only has three entries,
+ // while the min/max range has five.
+ mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
+ fail("The size of the displayed values array must be equal to min/max range!");
+ } catch (Exception e) {
+ // We are expecting to catch an exception. Set displayed values to an array that
+ // matches the min/max range.
+ mNumberPicker.setDisplayedValues(NUMBER_NAMES5);
+ }
+ });
+ }
+
+ public void testSelectionDisplayedValueFromDisplayedValues() {
+ mInstrumentation.runOnMainSync(() -> {
+ mNumberPicker.setMinValue(1);
+ mNumberPicker.setMaxValue(3);
+ mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
+ });
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+ assertTrue(TextUtils.equals(NUMBER_NAMES3[0],
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(2));
+ assertTrue(TextUtils.equals(NUMBER_NAMES3[1],
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(3));
+ assertTrue(TextUtils.equals(NUMBER_NAMES3[2],
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ // Switch to a different displayed values array
+ mInstrumentation.runOnMainSync(() -> {
+ mNumberPicker.setDisplayedValues(NUMBER_NAMES_ALT3);
+ });
+ assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[2],
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+ assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[0],
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(2));
+ assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[1],
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+ }
+
+ public void testSelectionDisplayedValueFromFormatter() {
+ mInstrumentation.runOnMainSync(() -> {
+ mNumberPicker.setMinValue(0);
+ mNumberPicker.setMaxValue(4);
+ mNumberPicker.setFormatter((int value) -> "entry " + value);
+ });
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(0));
+ assertTrue(TextUtils.equals("entry 0",
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+ assertTrue(TextUtils.equals("entry 1",
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(2));
+ assertTrue(TextUtils.equals("entry 2",
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(3));
+ assertTrue(TextUtils.equals("entry 3",
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(4));
+ assertTrue(TextUtils.equals("entry 4",
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ // Switch to a different formatter
+ mInstrumentation.runOnMainSync(
+ () -> mNumberPicker.setFormatter((int value) -> "row " + value));
+ // Check that the currently selected value has new displayed value
+ assertTrue(TextUtils.equals("row 4",
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ // and check a couple more values for the new formatting
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(0));
+ assertTrue(TextUtils.equals("row 0",
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+ assertTrue(TextUtils.equals("row 1",
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+ }
+
+
+ public void testSelectionDisplayedValuePrecedence() {
+ mInstrumentation.runOnMainSync(() -> {
+ mNumberPicker.setMinValue(1);
+ mNumberPicker.setMaxValue(3);
+ mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
+ mNumberPicker.setFormatter((int value) -> "entry " + value);
+ });
+
+ // According to the widget documentation, displayed values take precedence over formatter
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+ assertTrue(TextUtils.equals(NUMBER_NAMES3[0],
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(2));
+ assertTrue(TextUtils.equals(NUMBER_NAMES3[1],
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(3));
+ assertTrue(TextUtils.equals(NUMBER_NAMES3[2],
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ // Set displayed values to null and test that the widget is using the formatter
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setDisplayedValues(null));
+ assertTrue(TextUtils.equals("entry 3",
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+ assertTrue(TextUtils.equals("entry 1",
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(2));
+ assertTrue(TextUtils.equals("entry 2",
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ // Set a different displayed values array and test that it's taking precedence
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setDisplayedValues(NUMBER_NAMES_ALT3));
+ assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[1],
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(1));
+ assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[0],
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(3));
+ assertTrue(TextUtils.equals(NUMBER_NAMES_ALT3[2],
+ mNumberPicker.getDisplayedValueForCurrentSelection()));
+ }
+
+ public void testAccessValue() {
+ mInstrumentation.runOnMainSync(() -> {
+ mNumberPicker.setMinValue(20);
+ mNumberPicker.setMaxValue(22);
+ mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
+ });
+
+ final NumberPicker.OnValueChangeListener mockValueChangeListener =
+ mock(NumberPicker.OnValueChangeListener.class);
+ mNumberPicker.setOnValueChangedListener(mockValueChangeListener);
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(21));
+ assertEquals(21, mNumberPicker.getValue());
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(20));
+ assertEquals(20, mNumberPicker.getValue());
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(22));
+ assertEquals(22, mNumberPicker.getValue());
+
+ // Check trying to set value out of min/max range
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(10));
+ assertEquals(20, mNumberPicker.getValue());
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(100));
+ assertEquals(22, mNumberPicker.getValue());
+
+ // Since all changes to value are via API calls, we should have no interactions /
+ // callbacks on our listener.
+ verifyZeroInteractions(mockValueChangeListener);
+ }
+
+ public void testInteractionWithSwipeDown() {
+ mInstrumentation.runOnMainSync(() -> {
+ mNumberPicker.setMinValue(6);
+ mNumberPicker.setMaxValue(8);
+ mNumberPicker.setDisplayedValues(NUMBER_NAMES_ALT3);
+ });
+
+ final NumberPicker.OnValueChangeListener mockValueChangeListener =
+ mock(NumberPicker.OnValueChangeListener.class);
+ mNumberPicker.setOnValueChangedListener(mockValueChangeListener);
+
+ final NumberPicker.OnScrollListener mockScrollListener =
+ mock(NumberPicker.OnScrollListener.class);
+ mNumberPicker.setOnScrollListener(mockScrollListener);
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(7));
+ assertEquals(7, mNumberPicker.getValue());
+
+ // Swipe down across our number picker
+ final int[] numberPickerLocationOnScreen = new int[2];
+ mNumberPicker.getLocationOnScreen(numberPickerLocationOnScreen);
+
+ ViewTestUtils.emulateDragGesture(mInstrumentation,
+ numberPickerLocationOnScreen[0] + mNumberPicker.getWidth() / 2,
+ numberPickerLocationOnScreen[1] + 1,
+ 0,
+ mNumberPicker.getHeight() - 2);
+
+ // At this point we expect that the drag-down gesture has selected the value
+ // that was "above" the previously selected one, and that our value change listener
+ // has been notified of that change exactly once.
+ assertEquals(6, mNumberPicker.getValue());
+ verify(mockValueChangeListener, times(1)).onValueChange(mNumberPicker, 7, 6);
+ verifyNoMoreInteractions(mockValueChangeListener);
+
+ // We expect that our scroll listener will be called with specific state changes.
+ InOrder inOrder = inOrder(mockScrollListener);
+ inOrder.verify(mockScrollListener).onScrollStateChange(mNumberPicker,
+ NumberPicker.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
+ inOrder.verify(mockScrollListener).onScrollStateChange(mNumberPicker,
+ NumberPicker.OnScrollListener.SCROLL_STATE_IDLE);
+ verifyNoMoreInteractions(mockScrollListener);
+ }
+
+ public void testInteractionWithSwipeUp() {
+ mInstrumentation.runOnMainSync(() -> {
+ mNumberPicker.setMinValue(10);
+ mNumberPicker.setMaxValue(12);
+ mNumberPicker.setDisplayedValues(NUMBER_NAMES_ALT3);
+ });
+
+ final NumberPicker.OnValueChangeListener mockValueChangeListener =
+ mock(NumberPicker.OnValueChangeListener.class);
+ mNumberPicker.setOnValueChangedListener(mockValueChangeListener);
+
+ final NumberPicker.OnScrollListener mockScrollListener =
+ mock(NumberPicker.OnScrollListener.class);
+ mNumberPicker.setOnScrollListener(mockScrollListener);
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(11));
+ assertEquals(11, mNumberPicker.getValue());
+
+ // Swipe up across our number picker
+ final int[] numberPickerLocationOnScreen = new int[2];
+ mNumberPicker.getLocationOnScreen(numberPickerLocationOnScreen);
+
+ ViewTestUtils.emulateDragGesture(mInstrumentation,
+ numberPickerLocationOnScreen[0] + mNumberPicker.getWidth() / 2,
+ numberPickerLocationOnScreen[1] + mNumberPicker.getHeight() - 1,
+ 0,
+ - (mNumberPicker.getHeight() - 2));
+
+ // At this point we expect that the drag-up gesture has selected the value
+ // that was "below" the previously selected one, and that our value change listener
+ // has been notified of that change exactly once.
+ assertEquals(12, mNumberPicker.getValue());
+ verify(mockValueChangeListener, times(1)).onValueChange(mNumberPicker, 11, 12);
+ verifyNoMoreInteractions(mockValueChangeListener);
+
+ // We expect that our scroll listener will be called with specific state changes.
+ InOrder inOrder = inOrder(mockScrollListener);
+ inOrder.verify(mockScrollListener).onScrollStateChange(mNumberPicker,
+ NumberPicker.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
+ inOrder.verify(mockScrollListener).onScrollStateChange(mNumberPicker,
+ NumberPicker.OnScrollListener.SCROLL_STATE_IDLE);
+ verifyNoMoreInteractions(mockScrollListener);
+ }
+
+ public void testAccessWrapSelectorValue() {
+ mInstrumentation.runOnMainSync(() -> {
+ mNumberPicker.setMinValue(100);
+ mNumberPicker.setMaxValue(200);
+ });
+ // As specified in the Javadocs of NumberPicker.setWrapSelectorWheel, when min/max
+ // range is larger than what the widget is showing, the selector wheel is enabled.
+ assertTrue(mNumberPicker.getWrapSelectorWheel());
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setWrapSelectorWheel(false));
+ assertFalse(mNumberPicker.getWrapSelectorWheel());
+
+ mInstrumentation.runOnMainSync(() -> mNumberPicker.setWrapSelectorWheel(true));
+ assertTrue(mNumberPicker.getWrapSelectorWheel());
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java b/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
index ee38448..aa37127 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
@@ -30,6 +30,7 @@
import android.view.View;
import android.widget.EditText;
import android.widget.PopupMenu;
+import android.widget.cts.util.ViewTestUtils;
import static org.mockito.Mockito.*;
@@ -183,15 +184,7 @@
runTestOnUiThread(() -> mBuilder.show());
mInstrumentation.waitForIdleSync();
- // Determine the location of the anchor on the screen so that we can emulate
- // a tap outside of the popup bounds to dismiss the popup
- final int[] anchorOnScreenXY = new int[2];
- mBuilder.mAnchor.getLocationOnScreen(anchorOnScreenXY);
-
- int emulatedTapX = anchorOnScreenXY[0] + 10;
- int emulatedTapY = anchorOnScreenXY[1] - 20;
-
- // The logic below uses Instrumentation to emulate a tap outside the bounds of the
+ // The call below uses Instrumentation to emulate a tap outside the bounds of the
// displayed popup menu. This tap is then treated by the framework to be "split" as
// the ACTION_OUTSIDE for the popup itself, as well as DOWN / MOVE / UP for the underlying
// view root if the popup is not modal.
@@ -200,27 +193,7 @@
// of Instrumentation is necessary here since Espresso's actions operate at the level
// of view or data. Also, we don't want to use View.dispatchTouchEvent directly as
// that would require emulation of two separate sequences as well.
-
- // Inject DOWN event
- long downTime = SystemClock.uptimeMillis();
- MotionEvent eventDown = MotionEvent.obtain(
- downTime, downTime, MotionEvent.ACTION_DOWN, emulatedTapX, emulatedTapY, 1);
- mInstrumentation.sendPointerSync(eventDown);
-
- // Inject MOVE event
- long moveTime = SystemClock.uptimeMillis();
- MotionEvent eventMove = MotionEvent.obtain(
- moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedTapX, emulatedTapY, 1);
- mInstrumentation.sendPointerSync(eventMove);
-
- // Inject UP event
- long upTime = SystemClock.uptimeMillis();
- MotionEvent eventUp = MotionEvent.obtain(
- upTime, upTime, MotionEvent.ACTION_UP, emulatedTapX, emulatedTapY, 1);
- mInstrumentation.sendPointerSync(eventUp);
-
- // Wait for the system to process all events in the queue
- mInstrumentation.waitForIdleSync();
+ ViewTestUtils.emulateTapOnScreen(mInstrumentation, mBuilder.mAnchor, 10, -20);
// At this point our popup should have notified its dismiss listener
verify(mBuilder.mOnDismissListener, times(1)).onDismiss(mPopupMenu);
diff --git a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
index 96b37d3..9da8c5d 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
@@ -20,12 +20,14 @@
import android.app.Instrumentation;
import android.content.Context;
import android.graphics.Color;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
import android.transition.Transition;
import android.transition.Transition.TransitionListener;
import android.transition.TransitionValues;
@@ -51,6 +53,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+@SmallTest
public class PopupWindowTest extends
ActivityInstrumentationTestCase2<PopupWindowCtsActivity> {
private Instrumentation mInstrumentation;
@@ -84,6 +87,14 @@
new PopupWindow(mActivity, null, android.R.attr.popupWindowStyle);
+ new PopupWindow(mActivity, null, 0, android.R.style.Widget_DeviceDefault_PopupWindow);
+
+ new PopupWindow(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_PopupWindow);
+
+ new PopupWindow(mActivity, null, 0, android.R.style.Widget_Material_PopupWindow);
+
+ new PopupWindow(mActivity, null, 0, android.R.style.Widget_Material_Light_PopupWindow);
+
mPopupWindow = new PopupWindow();
assertEquals(0, mPopupWindow.getWidth());
assertEquals(0, mPopupWindow.getHeight());
@@ -575,6 +586,8 @@
// Do not attach within the decor; we will be measuring location
// with regard to screen coordinates.
mPopupWindow.setAttachedInDecor(false);
+ assertFalse(mPopupWindow.isAttachedInDecor());
+
final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
final int xOff = 10;
@@ -656,42 +669,73 @@
public void testGetMaxAvailableHeight() {
mPopupWindow = createPopupWindow(createPopupContent(50, 50));
+ final Point point = new Point();
+ getDisplay().getSize(point);
+ final int displayHeight = point.y;
View anchorView = mActivity.findViewById(R.id.anchor_upper);
- int avaliable = getDisplay().getHeight() - anchorView.getHeight();
+ int available = displayHeight - anchorView.getHeight();
int maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
+ int maxAvailableHeightIgnoringBottomDecoration =
+ mPopupWindow.getMaxAvailableHeight(anchorView, 0, true);
assertTrue(maxAvailableHeight > 0);
- assertTrue(maxAvailableHeight <= avaliable);
+ assertTrue(maxAvailableHeight <= available);
+ assertTrue(maxAvailableHeightIgnoringBottomDecoration >= maxAvailableHeight);
+ assertTrue(maxAvailableHeightIgnoringBottomDecoration <= available);
+
int maxAvailableHeightWithOffset = mPopupWindow.getMaxAvailableHeight(anchorView, 2);
assertEquals(maxAvailableHeight - 2, maxAvailableHeightWithOffset);
+
maxAvailableHeightWithOffset =
mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight);
assertTrue(maxAvailableHeightWithOffset > 0);
- assertTrue(maxAvailableHeightWithOffset <= avaliable);
+ assertTrue(maxAvailableHeightWithOffset <= available);
+
maxAvailableHeightWithOffset =
mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight / 2 - 1);
assertTrue(maxAvailableHeightWithOffset > 0);
- assertTrue(maxAvailableHeightWithOffset <= avaliable);
+ assertTrue(maxAvailableHeightWithOffset <= available);
+
maxAvailableHeightWithOffset = mPopupWindow.getMaxAvailableHeight(anchorView, -1);
assertTrue(maxAvailableHeightWithOffset > 0);
- assertTrue(maxAvailableHeightWithOffset <= avaliable);
+ assertTrue(maxAvailableHeightWithOffset <= available);
+
+ int maxAvailableHeightWithOffsetIgnoringBottomDecoration =
+ mPopupWindow.getMaxAvailableHeight(anchorView, 2, true);
+ assertEquals(maxAvailableHeightIgnoringBottomDecoration - 2,
+ maxAvailableHeightWithOffsetIgnoringBottomDecoration);
+
+ maxAvailableHeightWithOffsetIgnoringBottomDecoration =
+ mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight, true);
+ assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration > 0);
+ assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration <= available);
+
+ maxAvailableHeightWithOffsetIgnoringBottomDecoration =
+ mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight / 2 - 1, true);
+ assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration > 0);
+ assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration <= available);
+
+ maxAvailableHeightWithOffsetIgnoringBottomDecoration =
+ mPopupWindow.getMaxAvailableHeight(anchorView, -1, true);
+ assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration > 0);
+ assertTrue(maxAvailableHeightWithOffsetIgnoringBottomDecoration <= available);
anchorView = mActivity.findViewById(R.id.anchor_lower);
// On some devices the view might actually have larger size than the physical display
// due to chin and content will be laid out as if outside of the display. We need to use
// larger from the display height and the main view height.
- avaliable = Math.max(getDisplay().getHeight(),
+ available = Math.max(displayHeight,
mActivity.findViewById(android.R.id.content).getHeight()) - anchorView.getHeight();
maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
assertTrue(maxAvailableHeight > 0);
- assertTrue(maxAvailableHeight <= avaliable);
+ assertTrue(maxAvailableHeight <= available);
anchorView = mActivity.findViewById(R.id.anchor_middle_left);
- avaliable = getDisplay().getHeight() - anchorView.getHeight()
+ available = displayHeight - anchorView.getHeight()
- mActivity.findViewById(R.id.anchor_upper).getHeight();
maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
assertTrue(maxAvailableHeight > 0);
- assertTrue(maxAvailableHeight <= avaliable);
+ assertTrue(maxAvailableHeight <= available);
}
@UiThreadTest
@@ -815,6 +859,7 @@
mInstrumentation.waitForIdleSync();
// Do not update if it is not shown
assertFalse(mPopupWindow.isShowing());
+ assertFalse(mPopupWindow.isAttachedInDecor());
assertEquals(100, mPopupWindow.getWidth());
assertEquals(100, mPopupWindow.getHeight());
@@ -822,6 +867,14 @@
mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
// update if it is not shown
+ mInstrumentation.runOnMainSync(() -> mPopupWindow.update(80, 80));
+
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mPopupWindow.isShowing());
+ assertEquals(80, mPopupWindow.getWidth());
+ assertEquals(80, mPopupWindow.getHeight());
+
+ // update if it is not shown
mInstrumentation.runOnMainSync(() -> mPopupWindow.update(20, 50, 50, 50));
mInstrumentation.waitForIdleSync();
@@ -1061,6 +1114,61 @@
assertEquals(LayoutParams.MATCH_PARENT, p.height);
}
+ public void testAccessElevation() {
+ mPopupWindow = createPopupWindow(createPopupContent(50, 50));
+ mInstrumentation.runOnMainSync(() -> mPopupWindow.setElevation(2.0f));
+
+ showPopup();
+ assertEquals(2.0f, mPopupWindow.getElevation());
+
+ dismissPopup();
+ mInstrumentation.runOnMainSync(() -> mPopupWindow.setElevation(4.0f));
+ showPopup();
+ assertEquals(4.0f, mPopupWindow.getElevation());
+
+ dismissPopup();
+ mInstrumentation.runOnMainSync(() -> mPopupWindow.setElevation(10.0f));
+ showPopup();
+ assertEquals(10.0f, mPopupWindow.getElevation());
+ }
+
+ public void testAccessSoftInputMode() {
+ mPopupWindow = createPopupWindow(createPopupContent(50, 50));
+ mInstrumentation.runOnMainSync(
+ () -> mPopupWindow.setSoftInputMode(
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE));
+
+ showPopup();
+ assertEquals(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE,
+ mPopupWindow.getSoftInputMode());
+
+ dismissPopup();
+ mInstrumentation.runOnMainSync(
+ () -> mPopupWindow.setSoftInputMode(
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN));
+ showPopup();
+ assertEquals(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN,
+ mPopupWindow.getSoftInputMode());
+ }
+
+ public void testAccessSplitTouchEnabled() {
+ mPopupWindow = createPopupWindow(createPopupContent(50, 50));
+ mInstrumentation.runOnMainSync(() -> mPopupWindow.setSplitTouchEnabled(true));
+
+ showPopup();
+ assertTrue(mPopupWindow.isSplitTouchEnabled());
+
+ dismissPopup();
+ mInstrumentation.runOnMainSync(() -> mPopupWindow.setSplitTouchEnabled(false));
+ showPopup();
+ assertFalse(mPopupWindow.isSplitTouchEnabled());
+
+ dismissPopup();
+ mInstrumentation.runOnMainSync(() -> mPopupWindow.setSplitTouchEnabled(true));
+ showPopup();
+ assertTrue(mPopupWindow.isSplitTouchEnabled());
+ }
+
private static class BaseTransition extends Transition {
@Override
public void captureStartValues(TransitionValues transitionValues) {}
diff --git a/tests/tests/widget/src/android/widget/cts/ProgressBarCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ProgressBarCtsActivity.java
index 8298d5f..2b3a45d 100644
--- a/tests/tests/widget/src/android/widget/cts/ProgressBarCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/ProgressBarCtsActivity.java
@@ -18,17 +18,18 @@
import android.app.Activity;
import android.os.Bundle;
+import android.widget.ProgressBar;
/**
- * An application for ProgressBar test
- *
+ * A minimal application for {@link ProgressBar} test.
*/
public class ProgressBarCtsActivity extends Activity {
/**
- * Called with the activity is first created.
+ * Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ setContentView(R.layout.progressbar_layout);
}
}
diff --git a/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java b/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
index 1cf7334..040b26d 100644
--- a/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
@@ -16,412 +16,449 @@
package android.widget.cts;
+import android.content.Context;
import android.content.res.ColorStateList;
+import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
-import android.view.LayoutInflater;
-
-import android.widget.cts.R;
-
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Parcelable;
-import android.test.InstrumentationTestCase;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AccelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ProgressBar;
+import android.widget.cts.util.TestUtils;
-public class ProgressBarTest extends InstrumentationTestCase {
- // The target context.
- private Context mContext;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
+
+@SmallTest
+public class ProgressBarTest extends ActivityInstrumentationTestCase2<ProgressBarCtsActivity> {
+ private ProgressBarCtsActivity mActivity;
+ private ProgressBar mProgressBar;
+ private ProgressBar mProgressBarHorizontal;
+
+ public ProgressBarTest() {
+ super("android.widget.cts", ProgressBarCtsActivity.class);
+ }
@Override
protected void setUp() throws Exception {
super.setUp();
- mContext = getInstrumentation().getTargetContext();
+
+ mActivity = getActivity();
+ mProgressBar = (ProgressBar) mActivity.findViewById(R.id.progress);
+ mProgressBarHorizontal = (ProgressBar) mActivity.findViewById(R.id.progress_horizontal);
}
public void testConstructor() {
- new ProgressBar(mContext);
+ new ProgressBar(mActivity);
- new ProgressBar(mContext, null);
+ new ProgressBar(mActivity, null);
- new ProgressBar(mContext, null, android.R.attr.progressBarStyle);
+ new ProgressBar(mActivity, null, android.R.attr.progressBarStyle);
+
+ new ProgressBar(mActivity, null, android.R.attr.progressBarStyleHorizontal);
+
+ new ProgressBar(mActivity, null, android.R.attr.progressBarStyleInverse);
+
+ new ProgressBar(mActivity, null, android.R.attr.progressBarStyleLarge);
+
+ new ProgressBar(mActivity, null, android.R.attr.progressBarStyleLargeInverse);
+
+ new ProgressBar(mActivity, null, android.R.attr.progressBarStyleSmall);
+
+ new ProgressBar(mActivity, null, android.R.attr.progressBarStyleSmallInverse);
+
+ new ProgressBar(mActivity, null, android.R.attr.progressBarStyleSmallTitle);
+
+ new ProgressBar(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_ProgressBar);
+
+ new ProgressBar(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_Light_ProgressBar_Horizontal);
+
+ new ProgressBar(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_Light_ProgressBar_Inverse);
+
+ new ProgressBar(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_Light_ProgressBar_Large);
+
+ new ProgressBar(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_Light_ProgressBar_Large_Inverse);
+
+ new ProgressBar(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_Light_ProgressBar_Small);
+
+ new ProgressBar(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_Light_ProgressBar_Small_Inverse);
+
+ new ProgressBar(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_Light_ProgressBar_Small_Title);
+
+ new ProgressBar(mActivity, null, 0, android.R.style.Widget_Material_Light_ProgressBar);
+
+ new ProgressBar(mActivity, null, 0,
+ android.R.style.Widget_Material_Light_ProgressBar_Horizontal);
+
+ new ProgressBar(mActivity, null, 0,
+ android.R.style.Widget_Material_Light_ProgressBar_Inverse);
+
+ new ProgressBar(mActivity, null, 0,
+ android.R.style.Widget_Material_Light_ProgressBar_Large);
+
+ new ProgressBar(mActivity, null, 0,
+ android.R.style.Widget_Material_Light_ProgressBar_Large_Inverse);
+
+ new ProgressBar(mActivity, null, 0,
+ android.R.style.Widget_Material_Light_ProgressBar_Small);
+
+ new ProgressBar(mActivity, null, 0,
+ android.R.style.Widget_Material_Light_ProgressBar_Small_Inverse);
+
+ new ProgressBar(mActivity, null, 0,
+ android.R.style.Widget_Material_Light_ProgressBar_Small_Title);
}
+ @UiThreadTest
public void testSetIndeterminate() {
- ProgressBar progressBar = new ProgressBar(mContext);
- assertTrue(progressBar.isIndeterminate());
+ assertTrue(mProgressBar.isIndeterminate());
- progressBar.setIndeterminate(true);
- assertTrue(progressBar.isIndeterminate());
+ mProgressBar.setIndeterminate(true);
+ assertTrue(mProgressBar.isIndeterminate());
- progressBar.setIndeterminate(false);
+ mProgressBar.setIndeterminate(false);
// because default is Indeterminate only progressBar, can't change the status
- assertTrue(progressBar.isIndeterminate());
+ assertTrue(mProgressBar.isIndeterminate());
- progressBar = new ProgressBar(mContext, null, android.R.attr.progressBarStyleHorizontal);
- assertFalse(progressBar.isIndeterminate());
+ assertFalse(mProgressBarHorizontal.isIndeterminate());
- progressBar.setIndeterminate(true);
- assertTrue(progressBar.isIndeterminate());
+ mProgressBarHorizontal.setIndeterminate(true);
+ assertTrue(mProgressBarHorizontal.isIndeterminate());
- progressBar.setIndeterminate(false);
- assertFalse(progressBar.isIndeterminate());
+ mProgressBarHorizontal.setIndeterminate(false);
+ assertFalse(mProgressBarHorizontal.isIndeterminate());
}
+ @UiThreadTest
public void testAccessIndeterminateDrawable() {
- ProgressBar progressBar = new ProgressBar(mContext);
-
// set IndeterminateDrawable
// normal value
- MockDrawable mockDrawable = new MockDrawable();
- progressBar.setIndeterminateDrawable(mockDrawable);
- assertSame(mockDrawable, progressBar.getIndeterminateDrawable());
- assertFalse(mockDrawable.hasCalledDraw());
- progressBar.draw(new Canvas());
- assertTrue(mockDrawable.hasCalledDraw());
+ Drawable mockProgressDrawable = spy(new ColorDrawable(Color.YELLOW));
+ mProgressBar.setIndeterminateDrawable(mockProgressDrawable);
+ assertSame(mockProgressDrawable, mProgressBar.getIndeterminateDrawable());
+ verify(mockProgressDrawable, never()).draw(any(Canvas.class));
+ mProgressBar.draw(new Canvas());
+ verify(mockProgressDrawable, atLeastOnce()).draw(any(Canvas.class));
// exceptional value
- progressBar.setIndeterminateDrawable(null);
- assertNull(progressBar.getIndeterminateDrawable());
+ mProgressBar.setIndeterminateDrawable(null);
+ assertNull(mProgressBar.getIndeterminateDrawable());
}
+ @UiThreadTest
public void testAccessProgressDrawable() {
- ProgressBar progressBar = new ProgressBar(mContext, null,
- android.R.attr.progressBarStyleHorizontal);
-
// set ProgressDrawable
// normal value
- MockDrawable mockDrawable = new MockDrawable();
- progressBar.setProgressDrawable(mockDrawable);
- assertSame(mockDrawable, progressBar.getProgressDrawable());
- assertFalse(mockDrawable.hasCalledDraw());
- progressBar.draw(new Canvas());
- assertTrue(mockDrawable.hasCalledDraw());
+ Drawable mockProgressDrawable = spy(new ColorDrawable(Color.BLUE));
+ mProgressBarHorizontal.setProgressDrawable(mockProgressDrawable);
+ assertSame(mockProgressDrawable, mProgressBarHorizontal.getProgressDrawable());
+ verify(mockProgressDrawable, never()).draw(any(Canvas.class));
+ mProgressBarHorizontal.draw(new Canvas());
+ verify(mockProgressDrawable, atLeastOnce()).draw(any(Canvas.class));
// exceptional value
- progressBar.setProgressDrawable(null);
- assertNull(progressBar.getProgressDrawable());
+ mProgressBarHorizontal.setProgressDrawable(null);
+ assertNull(mProgressBarHorizontal.getProgressDrawable());
}
+ @UiThreadTest
public void testAccessProgress() {
- ProgressBar progressBar = new ProgressBar(mContext, null,
- android.R.attr.progressBarStyleHorizontal);
- assertEquals(0, progressBar.getProgress());
+ assertEquals(0, mProgressBarHorizontal.getProgress());
- final int maxProgress = progressBar.getMax();
+ final int maxProgress = mProgressBarHorizontal.getMax();
// set Progress
// normal value
- progressBar.setProgress(maxProgress >> 1);
- assertEquals(maxProgress >> 1, progressBar.getProgress());
+ mProgressBarHorizontal.setProgress(maxProgress >> 1);
+ assertEquals(maxProgress >> 1, mProgressBarHorizontal.getProgress());
// exceptional values
- progressBar.setProgress(-1);
- assertEquals(0, progressBar.getProgress());
+ mProgressBarHorizontal.setProgress(-1);
+ assertEquals(0, mProgressBarHorizontal.getProgress());
- progressBar.setProgress(maxProgress + 1);
- assertEquals(maxProgress, progressBar.getProgress());
+ mProgressBarHorizontal.setProgress(maxProgress + 1);
+ assertEquals(maxProgress, mProgressBarHorizontal.getProgress());
- progressBar.setProgress(Integer.MAX_VALUE);
- assertEquals(maxProgress, progressBar.getProgress());
+ mProgressBarHorizontal.setProgress(Integer.MAX_VALUE);
+ assertEquals(maxProgress, mProgressBarHorizontal.getProgress());
+
+ mProgressBarHorizontal.setProgress(0, true);
+ assertEquals(0, mProgressBarHorizontal.getProgress());
// when in indeterminate mode
- progressBar.setIndeterminate(true);
- progressBar.setProgress(maxProgress >> 1);
- assertEquals(0, progressBar.getProgress());
+ mProgressBarHorizontal.setIndeterminate(true);
+ mProgressBarHorizontal.setProgress(maxProgress >> 1);
+ assertEquals(0, mProgressBarHorizontal.getProgress());
}
+ @UiThreadTest
public void testAccessSecondaryProgress() {
- ProgressBar progressBar = new ProgressBar(mContext, null,
- android.R.attr.progressBarStyleHorizontal);
- assertEquals(0, progressBar.getSecondaryProgress());
+ assertEquals(0, mProgressBarHorizontal.getSecondaryProgress());
- final int maxProgress = progressBar.getMax();
+ final int maxProgress = mProgressBarHorizontal.getMax();
// set SecondaryProgress
// normal value
- progressBar.setSecondaryProgress(maxProgress >> 1);
- assertEquals(maxProgress >> 1, progressBar.getSecondaryProgress());
+ mProgressBarHorizontal.setSecondaryProgress(maxProgress >> 1);
+ assertEquals(maxProgress >> 1, mProgressBarHorizontal.getSecondaryProgress());
// exceptional value
- progressBar.setSecondaryProgress(-1);
- assertEquals(0, progressBar.getSecondaryProgress());
+ mProgressBarHorizontal.setSecondaryProgress(-1);
+ assertEquals(0, mProgressBarHorizontal.getSecondaryProgress());
- progressBar.setSecondaryProgress(maxProgress + 1);
- assertEquals(maxProgress, progressBar.getSecondaryProgress());
+ mProgressBarHorizontal.setSecondaryProgress(maxProgress + 1);
+ assertEquals(maxProgress, mProgressBarHorizontal.getSecondaryProgress());
- progressBar.setSecondaryProgress(Integer.MAX_VALUE);
- assertEquals(maxProgress, progressBar.getSecondaryProgress());
+ mProgressBarHorizontal.setSecondaryProgress(Integer.MAX_VALUE);
+ assertEquals(maxProgress, mProgressBarHorizontal.getSecondaryProgress());
// when in indeterminate mode
- progressBar.setIndeterminate(true);
- progressBar.setSecondaryProgress(maxProgress >> 1);
- assertEquals(0, progressBar.getSecondaryProgress());
+ mProgressBarHorizontal.setIndeterminate(true);
+ mProgressBarHorizontal.setSecondaryProgress(maxProgress >> 1);
+ assertEquals(0, mProgressBarHorizontal.getSecondaryProgress());
}
+ @UiThreadTest
public void testIncrementProgressBy() {
- ProgressBar progressBar = new ProgressBar(mContext, null,
- android.R.attr.progressBarStyleHorizontal);
-
// normal value
int increment = 1;
- int oldProgress = progressBar.getProgress();
- progressBar.incrementProgressBy(increment);
- assertEquals(oldProgress + increment, progressBar.getProgress());
+ int oldProgress = mProgressBarHorizontal.getProgress();
+ mProgressBarHorizontal.incrementProgressBy(increment);
+ assertEquals(oldProgress + increment, mProgressBarHorizontal.getProgress());
- increment = progressBar.getMax() >> 1;
- oldProgress = progressBar.getProgress();
- progressBar.incrementProgressBy(increment);
- assertEquals(oldProgress + increment, progressBar.getProgress());
+ increment = mProgressBarHorizontal.getMax() >> 1;
+ oldProgress = mProgressBarHorizontal.getProgress();
+ mProgressBarHorizontal.incrementProgressBy(increment);
+ assertEquals(oldProgress + increment, mProgressBarHorizontal.getProgress());
// exceptional values
- progressBar.setProgress(0);
- progressBar.incrementProgressBy(Integer.MAX_VALUE);
- assertEquals(progressBar.getMax(), progressBar.getProgress());
+ mProgressBarHorizontal.setProgress(0);
+ mProgressBarHorizontal.incrementProgressBy(Integer.MAX_VALUE);
+ assertEquals(mProgressBarHorizontal.getMax(), mProgressBarHorizontal.getProgress());
- progressBar.setProgress(0);
- progressBar.incrementProgressBy(Integer.MIN_VALUE);
- assertEquals(0, progressBar.getProgress());
+ mProgressBarHorizontal.setProgress(0);
+ mProgressBarHorizontal.incrementProgressBy(Integer.MIN_VALUE);
+ assertEquals(0, mProgressBarHorizontal.getProgress());
}
+ @UiThreadTest
public void testIncrementSecondaryProgressBy() {
- ProgressBar progressBar = new ProgressBar(mContext, null,
- android.R.attr.progressBarStyleHorizontal);
-
// normal value
int increment = 1;
- int oldSecondaryProgress = progressBar.getSecondaryProgress();
- progressBar.incrementSecondaryProgressBy(increment);
- assertEquals(oldSecondaryProgress + increment, progressBar.getSecondaryProgress());
+ int oldSecondaryProgress = mProgressBarHorizontal.getSecondaryProgress();
+ mProgressBarHorizontal.incrementSecondaryProgressBy(increment);
+ assertEquals(oldSecondaryProgress + increment,
+ mProgressBarHorizontal.getSecondaryProgress());
- increment = progressBar.getMax() >> 1;
- oldSecondaryProgress = progressBar.getSecondaryProgress();
- progressBar.incrementSecondaryProgressBy(increment);
- assertEquals(oldSecondaryProgress + increment, progressBar.getSecondaryProgress());
+ increment = mProgressBarHorizontal.getMax() >> 1;
+ oldSecondaryProgress = mProgressBarHorizontal.getSecondaryProgress();
+ mProgressBarHorizontal.incrementSecondaryProgressBy(increment);
+ assertEquals(oldSecondaryProgress + increment,
+ mProgressBarHorizontal.getSecondaryProgress());
// exceptional values
- progressBar.setSecondaryProgress(0);
- progressBar.incrementSecondaryProgressBy(Integer.MAX_VALUE);
- assertEquals(progressBar.getMax(), progressBar.getSecondaryProgress());
+ mProgressBarHorizontal.setSecondaryProgress(0);
+ mProgressBarHorizontal.incrementSecondaryProgressBy(Integer.MAX_VALUE);
+ assertEquals(mProgressBarHorizontal.getMax(),
+ mProgressBarHorizontal.getSecondaryProgress());
- progressBar.setSecondaryProgress(0);
- progressBar.incrementSecondaryProgressBy(Integer.MIN_VALUE);
- assertEquals(0, progressBar.getSecondaryProgress());
+ mProgressBarHorizontal.setSecondaryProgress(0);
+ mProgressBarHorizontal.incrementSecondaryProgressBy(Integer.MIN_VALUE);
+ assertEquals(0, mProgressBarHorizontal.getSecondaryProgress());
}
+ @UiThreadTest
public void testAccessInterpolator() {
- ProgressBar progressBar = new ProgressBar(mContext);
-
// default should be LinearInterpolator
- assertTrue(progressBar.getInterpolator() instanceof LinearInterpolator);
+ assertTrue(mProgressBar.getInterpolator() instanceof LinearInterpolator);
- // normal value
- Interpolator i = new AccelerateDecelerateInterpolator();
- progressBar.setInterpolator(i);
- assertEquals(i, progressBar.getInterpolator());
+ Interpolator interpolator = new AccelerateDecelerateInterpolator();
+ mProgressBar.setInterpolator(interpolator);
+ assertEquals(interpolator, mProgressBar.getInterpolator());
+
+ mProgressBar.setInterpolator(mActivity, android.R.anim.accelerate_interpolator);
+ assertTrue(mProgressBar.getInterpolator() instanceof AccelerateInterpolator);
}
+ @UiThreadTest
public void testSetVisibility() {
- ProgressBar progressBar = new ProgressBar(mContext, null,
- android.R.attr.progressBarStyleHorizontal);
-
// set visibility
// normal value
int visibility = View.VISIBLE;
- progressBar.setVisibility(visibility);
- assertEquals(visibility, progressBar.getVisibility());
+ mProgressBarHorizontal.setVisibility(visibility);
+ assertEquals(visibility, mProgressBarHorizontal.getVisibility());
visibility = View.GONE;
- progressBar.setVisibility(visibility);
- assertEquals(visibility, progressBar.getVisibility());
+ mProgressBarHorizontal.setVisibility(visibility);
+ assertEquals(visibility, mProgressBarHorizontal.getVisibility());
// exceptional value
visibility = 0xfffffff5; // -11
int mask = 0x0000000C; // View.VISIBILITY_MASK
- int expected = (progressBar.getVisibility() & ~mask) | (visibility & mask);
- progressBar.setVisibility(visibility);
- assertEquals(expected, progressBar.getVisibility());
+ int expected = (mProgressBarHorizontal.getVisibility() & ~mask) | (visibility & mask);
+ mProgressBarHorizontal.setVisibility(visibility);
+ assertEquals(expected, mProgressBarHorizontal.getVisibility());
visibility = 0x7fffffff; // Integer.MAX_VALUE;
- expected = (progressBar.getVisibility() & ~mask) | (visibility & mask);
- progressBar.setVisibility(Integer.MAX_VALUE);
- assertEquals(expected, progressBar.getVisibility());
+ expected = (mProgressBarHorizontal.getVisibility() & ~mask) | (visibility & mask);
+ mProgressBarHorizontal.setVisibility(Integer.MAX_VALUE);
+ assertEquals(expected, mProgressBarHorizontal.getVisibility());
}
+ @UiThreadTest
public void testInvalidateDrawable() {
- MockProgressBar mockProgressBar = new MockProgressBar(mContext);
+ ProgressBar mockProgressBar = spy(new ProgressBar(mActivity));
- MockDrawable mockDrawable1 = new MockDrawable();
- MockDrawable mockDrawable2 = new MockDrawable();
+ Drawable mockDrawable1 = spy(new ColorDrawable(Color.RED));
+ Drawable mockDrawable2 = spy(new ColorDrawable(Color.GREEN));
mockProgressBar.setBackgroundDrawable(mockDrawable1);
mockProgressBar.invalidateDrawable(mockDrawable1);
- assertTrue(mockProgressBar.hasCalledInvalidate());
+ verify(mockProgressBar, atLeastOnce()).invalidate(anyInt(), anyInt(), anyInt(), anyInt());
- mockProgressBar.reset();
+ reset(mockProgressBar);
mockProgressBar.invalidateDrawable(mockDrawable2);
- assertFalse(mockProgressBar.hasCalledInvalidate());
+ verify(mockProgressBar, never()).invalidate(anyInt(), anyInt(), anyInt(), anyInt());
mockProgressBar.setIndeterminateDrawable(mockDrawable1);
mockProgressBar.setProgressDrawable(mockDrawable2);
}
+ @UiThreadTest
public void testPostInvalidate() {
- MockProgressBar mockProgressBar = new MockProgressBar(mContext);
- mockProgressBar.postInvalidate();
+ mProgressBarHorizontal.postInvalidate();
}
+ @UiThreadTest
public void testAccessMax() {
- ProgressBar progressBar = new ProgressBar(mContext, null,
- android.R.attr.progressBarStyleHorizontal);
-
// set Progress
int progress = 10;
- progressBar.setProgress(progress);
+ mProgressBarHorizontal.setProgress(progress);
// normal value
int max = progress + 1;
- progressBar.setMax(max);
- assertEquals(max, progressBar.getMax());
- assertEquals(progress, progressBar.getProgress());
+ mProgressBarHorizontal.setMax(max);
+ assertEquals(max, mProgressBarHorizontal.getMax());
+ assertEquals(progress, mProgressBarHorizontal.getProgress());
max = progress - 1;
- progressBar.setMax(max);
- assertEquals(max, progressBar.getMax());
- assertEquals(max, progressBar.getProgress());
+ mProgressBarHorizontal.setMax(max);
+ assertEquals(max, mProgressBarHorizontal.getMax());
+ assertEquals(max, mProgressBarHorizontal.getProgress());
// exceptional values
- progressBar.setMax(-1);
- assertEquals(0, progressBar.getMax());
- assertEquals(0, progressBar.getProgress());
+ mProgressBarHorizontal.setMax(-1);
+ assertEquals(0, mProgressBarHorizontal.getMax());
+ assertEquals(0, mProgressBarHorizontal.getProgress());
- progressBar.setMax(Integer.MAX_VALUE);
- assertEquals(Integer.MAX_VALUE, progressBar.getMax());
- assertEquals(0, progressBar.getProgress());
+ mProgressBarHorizontal.setMax(Integer.MAX_VALUE);
+ assertEquals(Integer.MAX_VALUE, mProgressBarHorizontal.getMax());
+ assertEquals(0, mProgressBarHorizontal.getProgress());
}
public void testOnDraw() {
// Do not test, it's controlled by View. Implementation details
}
+ @UiThreadTest
public void testProgressTint() {
- LayoutInflater inflater = LayoutInflater.from(mContext);
- View layout = inflater.inflate(R.layout.progressbar_layout, null);
- ProgressBar inflatedView = (ProgressBar) layout.findViewById(R.id.progress_tint);
+ ProgressBar tintedProgressBar = (ProgressBar) mActivity.findViewById(R.id.progress_tint);
assertEquals("Progress tint inflated correctly",
- Color.WHITE, inflatedView.getProgressTintList().getDefaultColor());
+ Color.WHITE, tintedProgressBar.getProgressTintList().getDefaultColor());
assertEquals("Progress tint mode inflated correctly",
- PorterDuff.Mode.SRC_OVER, inflatedView.getProgressTintMode());
+ PorterDuff.Mode.SRC_OVER, tintedProgressBar.getProgressTintMode());
assertEquals("Progress background tint inflated correctly",
- Color.WHITE, inflatedView.getProgressBackgroundTintList().getDefaultColor());
+ Color.WHITE, tintedProgressBar.getProgressBackgroundTintList().getDefaultColor());
assertEquals("Progress background tint mode inflated correctly",
- PorterDuff.Mode.SRC_OVER, inflatedView.getProgressBackgroundTintMode());
+ PorterDuff.Mode.SRC_OVER, tintedProgressBar.getProgressBackgroundTintMode());
assertEquals("Secondary progress tint inflated correctly",
- Color.WHITE, inflatedView.getSecondaryProgressTintList().getDefaultColor());
+ Color.WHITE, tintedProgressBar.getSecondaryProgressTintList().getDefaultColor());
assertEquals("Secondary progress tint mode inflated correctly",
- PorterDuff.Mode.SRC_OVER, inflatedView.getSecondaryProgressTintMode());
+ PorterDuff.Mode.SRC_OVER, tintedProgressBar.getSecondaryProgressTintMode());
- MockDrawable progress = new MockDrawable();
- ProgressBar view = new ProgressBar(mContext);
+ Drawable mockProgressDrawable = spy(new ColorDrawable(Color.BLACK));
- view.setProgressDrawable(progress);
- assertFalse("No progress tint applied by default", progress.hasCalledSetTint());
+ mProgressBar.setProgressDrawable(mockProgressDrawable);
+ // No progress tint applied by default
+ verify(mockProgressDrawable, never()).setTintList(any(ColorStateList.class));
- view.setProgressBackgroundTintList(ColorStateList.valueOf(Color.WHITE));
- assertFalse("Progress background tint not applied when layer missing",
- progress.hasCalledSetTint());
+ mProgressBar.setProgressBackgroundTintList(ColorStateList.valueOf(Color.WHITE));
+ // Progress background tint not applied when layer missing
+ verify(mockProgressDrawable, never()).setTintList(any(ColorStateList.class));
- view.setSecondaryProgressTintList(ColorStateList.valueOf(Color.WHITE));
- assertFalse("Secondary progress tint not applied when layer missing",
- progress.hasCalledSetTint());
+ mProgressBar.setSecondaryProgressTintList(ColorStateList.valueOf(Color.WHITE));
+ // Secondary progress tint not applied when layer missing
+ verify(mockProgressDrawable, never()).setTintList(any(ColorStateList.class));
- view.setProgressTintList(ColorStateList.valueOf(Color.WHITE));
- assertTrue("Progress tint applied when setProgressTintList() called after setProgress()",
- progress.hasCalledSetTint());
+ mProgressBar.setProgressTintList(ColorStateList.valueOf(Color.WHITE));
+ // Progress tint applied when setProgressTintList() called after setProgress()
+ verify(mockProgressDrawable, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE));
- progress.reset();
- view.setProgressDrawable(null);
- view.setProgressDrawable(progress);
- assertTrue("Progress tint applied when setProgressTintList() called before setProgress()",
- progress.hasCalledSetTint());
+ mProgressBar.setProgressBackgroundTintMode(PorterDuff.Mode.DST_OVER);
+ assertEquals(PorterDuff.Mode.DST_OVER, mProgressBar.getProgressBackgroundTintMode());
+
+ mProgressBar.setSecondaryProgressTintMode(PorterDuff.Mode.DST_IN);
+ assertEquals(PorterDuff.Mode.DST_IN, mProgressBar.getSecondaryProgressTintMode());
+
+ mProgressBar.setProgressTintMode(PorterDuff.Mode.DST_ATOP);
+ assertEquals(PorterDuff.Mode.DST_ATOP, mProgressBar.getProgressTintMode());
+
+ reset(mockProgressDrawable);
+ mProgressBar.setProgressDrawable(null);
+ mProgressBar.setProgressDrawable(mockProgressDrawable);
+ // Progress tint applied when setProgressTintList() called before setProgress()
+ verify(mockProgressDrawable, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE));
}
+ @UiThreadTest
public void testIndeterminateTint() {
- LayoutInflater inflater = LayoutInflater.from(mContext);
- View layout = inflater.inflate(R.layout.progressbar_layout, null);
- ProgressBar inflatedView = (ProgressBar) layout.findViewById(R.id.indeterminate_tint);
+ ProgressBar tintedProgressBar =
+ (ProgressBar) mActivity.findViewById(R.id.indeterminate_tint);
assertEquals("Indeterminate tint inflated correctly",
- Color.WHITE, inflatedView.getIndeterminateTintList().getDefaultColor());
+ Color.WHITE, tintedProgressBar.getIndeterminateTintList().getDefaultColor());
assertEquals("Indeterminate tint mode inflated correctly",
- PorterDuff.Mode.SRC_OVER, inflatedView.getIndeterminateTintMode());
+ PorterDuff.Mode.SRC_OVER, tintedProgressBar.getIndeterminateTintMode());
- MockDrawable indeterminate = new MockDrawable();
- ProgressBar view = new ProgressBar(mContext);
+ Drawable mockIndeterminateDrawable = spy(new ColorDrawable(Color.MAGENTA));
- view.setIndeterminateDrawable(indeterminate);
- assertFalse("No indeterminate tint applied by default", indeterminate.hasCalledSetTint());
+ mProgressBar.setIndeterminateDrawable(mockIndeterminateDrawable);
+ // No indeterminate tint applied by default
+ verify(mockIndeterminateDrawable, never()).setTintList(any(ColorStateList.class));
- view.setIndeterminateTintList(ColorStateList.valueOf(Color.WHITE));
- assertTrue("Indeterminate tint applied when setIndeterminateTintList() called after "
- + "setIndeterminate()", indeterminate.hasCalledSetTint());
+ mProgressBar.setIndeterminateTintList(ColorStateList.valueOf(Color.RED));
+ // Indeterminate tint applied when setIndeterminateTintList() called after
+ // setIndeterminate()
+ verify(mockIndeterminateDrawable, times(1)).setTintList(
+ TestUtils.colorStateListOf(Color.RED));
- indeterminate.reset();
- view.setIndeterminateDrawable(null);
- view.setIndeterminateDrawable(indeterminate);
- assertTrue("Indeterminate tint applied when setIndeterminateTintList() called before "
- + "setIndeterminate()", indeterminate.hasCalledSetTint());
- }
+ mProgressBar.setIndeterminateTintMode(PorterDuff.Mode.LIGHTEN);
+ assertEquals(PorterDuff.Mode.LIGHTEN, mProgressBar.getIndeterminateTintMode());
- private class MockDrawable extends Drawable {
- private boolean mCalledDraw = false;
- private boolean mCalledSetTint = false;
-
- @Override
- public void draw(Canvas canvas) {
- mCalledDraw = true;
- }
-
- @Override
- public int getOpacity() {
- return 0;
- }
-
- @Override
- public void setAlpha(int alpha) {
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- }
-
- @Override
- public void setTintList(ColorStateList tint) {
- super.setTintList(tint);
- mCalledSetTint = true;
- }
-
- public boolean hasCalledSetTint() {
- return mCalledSetTint;
- }
-
- public boolean hasCalledDraw() {
- return mCalledDraw;
- }
-
- public void reset() {
- mCalledDraw = false;
- mCalledSetTint = false;
- }
-
+ reset(mockIndeterminateDrawable);
+ mProgressBar.setIndeterminateDrawable(null);
+ mProgressBar.setIndeterminateDrawable(mockIndeterminateDrawable);
+ // Indeterminate tint applied when setIndeterminateTintList() called before
+ // setIndeterminate()
+ verify(mockIndeterminateDrawable, times(1)).setTintList(
+ TestUtils.colorStateListOf(Color.RED));
}
public void testOnMeasure() {
@@ -432,13 +469,14 @@
// onSizeChanged() is implementation details, do NOT test
}
+ @UiThreadTest
public void testVerifyDrawable() {
- MockProgressBar mockProgressBar = new MockProgressBar(mContext);
+ MockProgressBar mockProgressBar = new MockProgressBar(mActivity);
assertTrue(mockProgressBar.verifyDrawable(null));
- Drawable d1 = mContext.getResources().getDrawable(R.drawable.blue);
- Drawable d2 = mContext.getResources().getDrawable(R.drawable.red);
- Drawable d3 = mContext.getResources().getDrawable(R.drawable.yellow);
+ Drawable d1 = mActivity.getResources().getDrawable(R.drawable.blue);
+ Drawable d2 = mActivity.getResources().getDrawable(R.drawable.red);
+ Drawable d3 = mActivity.getResources().getDrawable(R.drawable.yellow);
mockProgressBar.setBackgroundDrawable(d1);
assertTrue(mockProgressBar.verifyDrawable(null));
@@ -463,39 +501,33 @@
// drawableStateChanged() is implementation details, do NOT test
}
+ @UiThreadTest
public void testOnSaveAndRestoreInstanceState() {
- ProgressBar progressBar = new ProgressBar(mContext, null,
- android.R.attr.progressBarStyleHorizontal);
int oldProgress = 1;
- int oldSecondaryProgress = progressBar.getMax() - 1;
- progressBar.setProgress(oldProgress);
- progressBar.setSecondaryProgress(oldSecondaryProgress);
- assertEquals(oldProgress, progressBar.getProgress());
- assertEquals(oldSecondaryProgress, progressBar.getSecondaryProgress());
+ int oldSecondaryProgress = mProgressBarHorizontal.getMax() - 1;
+ mProgressBarHorizontal.setProgress(oldProgress);
+ mProgressBarHorizontal.setSecondaryProgress(oldSecondaryProgress);
+ assertEquals(oldProgress, mProgressBarHorizontal.getProgress());
+ assertEquals(oldSecondaryProgress, mProgressBarHorizontal.getSecondaryProgress());
- Parcelable state = progressBar.onSaveInstanceState();
+ Parcelable state = mProgressBarHorizontal.onSaveInstanceState();
int newProgress = 2;
- int newSecondaryProgress = progressBar.getMax() - 2;
- progressBar.setProgress(newProgress);
- progressBar.setSecondaryProgress(newSecondaryProgress);
- assertEquals(newProgress, progressBar.getProgress());
- assertEquals(newSecondaryProgress, progressBar.getSecondaryProgress());
+ int newSecondaryProgress = mProgressBarHorizontal.getMax() - 2;
+ mProgressBarHorizontal.setProgress(newProgress);
+ mProgressBarHorizontal.setSecondaryProgress(newSecondaryProgress);
+ assertEquals(newProgress, mProgressBarHorizontal.getProgress());
+ assertEquals(newSecondaryProgress, mProgressBarHorizontal.getSecondaryProgress());
- progressBar.onRestoreInstanceState(state);
- assertEquals(oldProgress, progressBar.getProgress());
- assertEquals(oldSecondaryProgress, progressBar.getSecondaryProgress());
+ mProgressBarHorizontal.onRestoreInstanceState(state);
+ assertEquals(oldProgress, mProgressBarHorizontal.getProgress());
+ assertEquals(oldSecondaryProgress, mProgressBarHorizontal.getSecondaryProgress());
}
/*
* Mock class for ProgressBar to test protected methods
*/
private class MockProgressBar extends ProgressBar {
- private boolean mCalledInvalidate = false;
-
- /**
- * @param context
- */
public MockProgressBar(Context context) {
super(context);
}
@@ -504,44 +536,5 @@
protected boolean verifyDrawable(Drawable who) {
return super.verifyDrawable(who);
}
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- }
-
- @Override
- protected synchronized void onMeasure(int widthMeasureSpec,
- int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
-
- @Override
- protected synchronized void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- }
-
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
- }
-
- public void invalidate(int l, int t, int r, int b) {
- mCalledInvalidate = true;
- super.invalidate(l, t, r, b);
- }
-
- public void invalidate() {
- mCalledInvalidate = true;
- super.invalidate();
- }
-
- public boolean hasCalledInvalidate() {
- return mCalledInvalidate;
- }
-
- public void reset() {
- mCalledInvalidate = false;
- }
}
}
diff --git a/tests/tests/widget/src/android/widget/cts/RadioButtonCtsActivity.java b/tests/tests/widget/src/android/widget/cts/RadioButtonCtsActivity.java
new file mode 100644
index 0000000..442d5f7
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/RadioButtonCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.RadioButton;
+
+/**
+ * A minimal application for {@link RadioButton} test.
+ */
+public class RadioButtonCtsActivity extends Activity {
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.radiobutton_layout);
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java b/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
index eb9387b..0b03557 100644
--- a/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
@@ -16,6 +16,12 @@
package android.widget.cts;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
+import android.widget.CheckBox;
import android.widget.cts.R;
@@ -24,59 +30,160 @@
import android.test.UiThreadTest;
import android.util.AttributeSet;
import android.widget.RadioButton;
+import android.widget.cts.util.ViewTestUtils;
-/**
- * Test {@link RadioButton}.
- */
-public class RadioButtonTest extends InstrumentationTestCase {
- private Context mContext;
+import static org.mockito.Mockito.*;
+
+@SmallTest
+public class RadioButtonTest extends ActivityInstrumentationTestCase2<RadioButtonCtsActivity> {
+ private Instrumentation mInstrumentation;
+ private Activity mActivity;
+ private RadioButton mRadioButton;
+
+ public RadioButtonTest() {
+ super("android.widget.cts", RadioButtonCtsActivity.class);
+ }
@Override
protected void setUp() throws Exception {
super.setUp();
- mContext = getInstrumentation().getTargetContext();
+
+ mInstrumentation = getInstrumentation();
+ mActivity = getActivity();
+ mRadioButton = (RadioButton) mActivity.findViewById(R.id.radio_button);
}
public void testConstructor() {
- AttributeSet attrs = mContext.getResources().getLayout(R.layout.radiogroup_1);
- assertNotNull(attrs);
+ new RadioButton(mActivity);
+ new RadioButton(mActivity, null);
+ new RadioButton(mActivity, null, android.R.attr.radioButtonStyle);
+ new RadioButton(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_CompoundButton_RadioButton);
+ new RadioButton(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_Light_CompoundButton_RadioButton);
+ new RadioButton(mActivity, null, 0,
+ android.R.style.Widget_Material_CompoundButton_RadioButton);
+ new RadioButton(mActivity, null, 0,
+ android.R.style.Widget_Material_Light_CompoundButton_RadioButton);
- new RadioButton(mContext);
try {
new RadioButton(null);
fail("The constructor should throw NullPointerException when param Context is null.");
} catch (NullPointerException e) {
}
- new RadioButton(mContext, attrs);
try {
- new RadioButton(null, attrs);
+ new RadioButton(null, null);
fail("The constructor should throw NullPointerException when param Context is null.");
} catch (NullPointerException e) {
}
- new RadioButton(mContext, null);
-
- new RadioButton(mContext, attrs, 0);
try {
- new RadioButton(null, attrs, 0);
+ new RadioButton(null, null, 0);
fail("The constructor should throw NullPointerException when param Context is null.");
} catch (NullPointerException e) {
}
- new RadioButton(mContext, null, 0);
- new RadioButton(mContext, attrs, Integer.MAX_VALUE);
- new RadioButton(mContext, attrs, Integer.MIN_VALUE);
}
- @UiThreadTest
- public void testToggle() {
- RadioButton button = new RadioButton(mContext);
- assertFalse(button.isChecked());
+ public void testText() {
+ assertTrue(TextUtils.equals(
+ mActivity.getString(R.string.hello_world), mRadioButton.getText()));
- button.toggle();
- assertTrue(button.isChecked());
+ mInstrumentation.runOnMainSync(() -> mRadioButton.setText("new text"));
+ assertTrue(TextUtils.equals("new text", mRadioButton.getText()));
- // Can't be toggled if it is checked
- button.toggle();
- assertTrue(button.isChecked());
+ mInstrumentation.runOnMainSync(() -> mRadioButton.setText(R.string.text_name));
+ assertTrue(TextUtils.equals(
+ mActivity.getString(R.string.text_name), mRadioButton.getText()));
+ }
+
+ public void testAccessChecked() {
+ final RadioButton.OnCheckedChangeListener mockCheckedChangeListener =
+ mock(RadioButton.OnCheckedChangeListener.class);
+ mRadioButton.setOnCheckedChangeListener(mockCheckedChangeListener);
+ verifyZeroInteractions(mockCheckedChangeListener);
+
+ assertFalse(mRadioButton.isChecked());
+
+ // not checked -> not checked
+ mInstrumentation.runOnMainSync(() -> mRadioButton.setChecked(false));
+ verifyZeroInteractions(mockCheckedChangeListener);
+ assertFalse(mRadioButton.isChecked());
+
+ // not checked -> checked
+ mInstrumentation.runOnMainSync(() -> mRadioButton.setChecked(true));
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+ assertTrue(mRadioButton.isChecked());
+
+ // checked -> checked
+ mInstrumentation.runOnMainSync(() -> mRadioButton.setChecked(true));
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+ assertTrue(mRadioButton.isChecked());
+
+ // checked -> not checked
+ mInstrumentation.runOnMainSync(() -> mRadioButton.setChecked(false));
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, false);
+ assertFalse(mRadioButton.isChecked());
+
+ verifyNoMoreInteractions(mockCheckedChangeListener);
+ }
+
+ public void testToggleViaApi() {
+ final RadioButton.OnCheckedChangeListener mockCheckedChangeListener =
+ mock(RadioButton.OnCheckedChangeListener.class);
+ mRadioButton.setOnCheckedChangeListener(mockCheckedChangeListener);
+ verifyZeroInteractions(mockCheckedChangeListener);
+
+ assertFalse(mRadioButton.isChecked());
+
+ // toggle to checked
+ mInstrumentation.runOnMainSync(() -> mRadioButton.toggle());
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+ assertTrue(mRadioButton.isChecked());
+
+ // try toggle to not checked - this should leave the radio button in checked state
+ mInstrumentation.runOnMainSync(() -> mRadioButton.toggle());
+ assertTrue(mRadioButton.isChecked());
+
+ verifyNoMoreInteractions(mockCheckedChangeListener);
+ }
+
+ public void testToggleViaEmulatedTap() {
+ final RadioButton.OnCheckedChangeListener mockCheckedChangeListener =
+ mock(RadioButton.OnCheckedChangeListener.class);
+ mRadioButton.setOnCheckedChangeListener(mockCheckedChangeListener);
+ verifyZeroInteractions(mockCheckedChangeListener);
+
+ assertFalse(mRadioButton.isChecked());
+
+ // tap to checked
+ ViewTestUtils.emulateTapOnViewCenter(mInstrumentation, mRadioButton);
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+ assertTrue(mRadioButton.isChecked());
+
+ // tap to not checked - this should leave the radio button in checked state
+ ViewTestUtils.emulateTapOnViewCenter(mInstrumentation, mRadioButton);
+ assertTrue(mRadioButton.isChecked());
+
+ verifyNoMoreInteractions(mockCheckedChangeListener);
+ }
+
+ public void testToggleViaPerformClick() {
+ final RadioButton.OnCheckedChangeListener mockCheckedChangeListener =
+ mock(RadioButton.OnCheckedChangeListener.class);
+ mRadioButton.setOnCheckedChangeListener(mockCheckedChangeListener);
+ verifyZeroInteractions(mockCheckedChangeListener);
+
+ assertFalse(mRadioButton.isChecked());
+
+ // click to checked
+ mInstrumentation.runOnMainSync(() -> mRadioButton.performClick());
+ verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mRadioButton, true);
+ assertTrue(mRadioButton.isChecked());
+
+ // click to not checked - this should leave the radio button in checked state
+ mInstrumentation.runOnMainSync(() -> mRadioButton.performClick());
+ assertTrue(mRadioButton.isChecked());
+
+ verifyNoMoreInteractions(mockCheckedChangeListener);
}
}
diff --git a/tests/tests/widget/src/android/widget/cts/RatingBarTest.java b/tests/tests/widget/src/android/widget/cts/RatingBarTest.java
index 669e7a1..aa5f3c8 100644
--- a/tests/tests/widget/src/android/widget/cts/RatingBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RatingBarTest.java
@@ -16,20 +16,21 @@
package android.widget.cts;
-import android.widget.cts.R;
-
-import android.content.Context;
+import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
import android.widget.RatingBar;
-import android.widget.RatingBar.OnRatingBarChangeListener;
+
+import static org.mockito.Mockito.*;
/**
* Test {@link RatingBar}.
*/
+@SmallTest
public class RatingBarTest extends ActivityInstrumentationTestCase2<RatingBarCtsActivity> {
- private Context mContext;
+ private Instrumentation mInstrumentation;
private RatingBarCtsActivity mActivity;
+ private RatingBar mRatingBar;
public RatingBarTest() {
super("android.widget.cts", RatingBarCtsActivity.class);
@@ -38,213 +39,137 @@
@Override
protected void setUp() throws Exception {
super.setUp();
+
+ mInstrumentation = getInstrumentation();
mActivity = getActivity();
- assertNotNull(mActivity);
- mContext = getInstrumentation().getContext();
+ mRatingBar = (RatingBar) mActivity.findViewById(R.id.ratingbar_constructor);
}
public void testConstructor() {
- new RatingBar(mContext, null, android.R.attr.ratingBarStyle);
-
- new RatingBar(mContext, null);
-
- new RatingBar(mContext);
-
- RatingBar ratingBar = (RatingBar) mActivity.findViewById(R.id.ratingbar_constructor);
- assertNotNull(ratingBar);
- assertFalse(ratingBar.isIndicator());
- assertEquals(50, ratingBar.getNumStars());
- assertEquals(1.2f, ratingBar.getRating());
- assertEquals(0.2f, ratingBar.getStepSize());
+ new RatingBar(mActivity);
+ new RatingBar(mActivity, null);
+ new RatingBar(mActivity, null, android.R.attr.ratingBarStyle);
+ new RatingBar(mActivity, null, 0, android.R.style.Widget_DeviceDefault_RatingBar);
+ new RatingBar(mActivity, null, 0, android.R.style.Widget_DeviceDefault_RatingBar_Indicator);
+ new RatingBar(mActivity, null, 0, android.R.style.Widget_DeviceDefault_RatingBar_Small);
+ new RatingBar(mActivity, null, 0, android.R.style.Widget_Material_RatingBar);
+ new RatingBar(mActivity, null, 0, android.R.style.Widget_Material_RatingBar_Indicator);
+ new RatingBar(mActivity, null, 0, android.R.style.Widget_Material_RatingBar_Small);
+ new RatingBar(mActivity, null, 0, android.R.style.Widget_Material_Light_RatingBar);
+ new RatingBar(mActivity, null, 0, android.R.style.Widget_Material_Light_RatingBar_Indicator);
+ new RatingBar(mActivity, null, 0, android.R.style.Widget_Material_Light_RatingBar_Small);
}
- @UiThreadTest
+ public void testAttributesFromLayout() {
+ assertFalse(mRatingBar.isIndicator());
+ assertEquals(50, mRatingBar.getNumStars());
+ assertEquals(1.2f, mRatingBar.getRating());
+ assertEquals(0.2f, mRatingBar.getStepSize());
+ }
+
public void testAccessOnRatingBarChangeListener() {
- RatingBar ratingBar = (RatingBar)mActivity.findViewById(R.id.ratingbar_constructor);
+ final RatingBar.OnRatingBarChangeListener listener =
+ mock(RatingBar.OnRatingBarChangeListener.class);
+ mRatingBar.setOnRatingBarChangeListener(listener);
+ assertSame(listener, mRatingBar.getOnRatingBarChangeListener());
+ verifyZeroInteractions(listener);
- MockOnRatingBarChangeListener listener = new MockOnRatingBarChangeListener();
-
- // set OnRatingBarChangeListener
// normal value
- ratingBar.setOnRatingBarChangeListener(listener);
- assertSame(listener, ratingBar.getOnRatingBarChangeListener());
- ratingBar.setRating(2.2f);
- assertTrue(listener.hasCalledOnRatingChanged());
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setRating(2.2f));
+ verify(listener, times(1)).onRatingChanged(mRatingBar, 2.2f, false);
// exceptional value
- listener.reset();
- ratingBar.setOnRatingBarChangeListener(null);
- assertNull(ratingBar.getOnRatingBarChangeListener());
- ratingBar.setRating(1.2f);
- assertFalse(listener.hasCalledOnRatingChanged());
+ mRatingBar.setOnRatingBarChangeListener(null);
+ assertNull(mRatingBar.getOnRatingBarChangeListener());
+ mRatingBar.setRating(1.2f);
+ verifyNoMoreInteractions(listener);
}
public void testAccessIndicator() {
- RatingBar ratingBar = new RatingBar(mContext);
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setIsIndicator(true));
+ assertTrue(mRatingBar.isIndicator());
- ratingBar.setIsIndicator(true);
- assertTrue(ratingBar.isIndicator());
-
- ratingBar.setIsIndicator(false);
- assertFalse(ratingBar.isIndicator());
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setIsIndicator(false));
+ assertFalse(mRatingBar.isIndicator());
}
public void testAccessNumStars() {
- MockRatingBar mockRatingBar = new MockRatingBar(mContext);
-
// set NumStars
// normal value
- assertFalse(mockRatingBar.hasCalledRequestLayout());
- mockRatingBar.setNumStars(20);
- assertTrue(mockRatingBar.hasCalledRequestLayout());
- assertEquals(20, mockRatingBar.getNumStars());
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setNumStars(20));
+ assertEquals(20, mRatingBar.getNumStars());
- // exceptional value
- mockRatingBar.reset();
- mockRatingBar.setNumStars(-10);
- assertFalse(mockRatingBar.hasCalledRequestLayout());
- assertEquals(20, mockRatingBar.getNumStars());
+ // invalid value - the currently set one stays
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setNumStars(-10));
+ assertEquals(20, mRatingBar.getNumStars());
- mockRatingBar.reset();
- mockRatingBar.setNumStars(Integer.MAX_VALUE);
- assertTrue(mockRatingBar.hasCalledRequestLayout());
- assertEquals(Integer.MAX_VALUE, mockRatingBar.getNumStars());
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setNumStars(Integer.MAX_VALUE));
+ assertEquals(Integer.MAX_VALUE, mRatingBar.getNumStars());
}
public void testAccessRating() {
- RatingBar ratingBar = new RatingBar(mContext);
-
// set Rating
// normal value
- ratingBar.setRating(2.0f);
- assertEquals(2.0f, ratingBar.getRating());
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setRating(2.0f));
+ assertEquals(2.0f, mRatingBar.getRating());
// exceptional value
- ratingBar.setRating(-2.0f);
- assertEquals(0f, ratingBar.getRating());
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setRating(-2.0f));
+ assertEquals(0f, mRatingBar.getRating());
- ratingBar.setRating(Float.MAX_VALUE);
- assertEquals((float) ratingBar.getNumStars(), ratingBar.getRating());
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setRating(Float.MAX_VALUE));
+ assertEquals((float) mRatingBar.getNumStars(), mRatingBar.getRating());
}
public void testSetMax() {
- RatingBar ratingBar = new RatingBar(mContext);
-
// normal value
- ratingBar.setMax(10);
- assertEquals(10, ratingBar.getMax());
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setMax(10));
+ assertEquals(10, mRatingBar.getMax());
- ratingBar.setProgress(10);
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setProgress(10));
// exceptional values
- ratingBar.setMax(-10);
- assertEquals(10, ratingBar.getMax());
- assertEquals(10, ratingBar.getProgress());
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setMax(-10));
+ assertEquals(10, mRatingBar.getMax());
+ assertEquals(10, mRatingBar.getProgress());
- ratingBar.setMax(Integer.MAX_VALUE);
- assertEquals(Integer.MAX_VALUE, ratingBar.getMax());
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setMax(Integer.MAX_VALUE));
+ assertEquals(Integer.MAX_VALUE, mRatingBar.getMax());
}
public void testAccessStepSize() {
- RatingBar ratingBar = new RatingBar(mContext);
-
// normal value
- ratingBar.setStepSize(1.5f);
- float expectedMax = ratingBar.getNumStars() / ratingBar.getStepSize();
- float expectedProgress = expectedMax / ratingBar.getMax() * ratingBar.getProgress();
- assertEquals((int) expectedMax, ratingBar.getMax());
- assertEquals((int) expectedProgress, ratingBar.getProgress());
- assertEquals((float) ratingBar.getNumStars() / (int) (ratingBar.getNumStars() / 1.5f),
- ratingBar.getStepSize());
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setStepSize(1.5f));
+ final float expectedMax = mRatingBar.getNumStars() / mRatingBar.getStepSize();
+ final float expectedProgress = expectedMax / mRatingBar.getMax() * mRatingBar.getProgress();
+ assertEquals((int) expectedMax, mRatingBar.getMax());
+ assertEquals((int) expectedProgress, mRatingBar.getProgress());
+ assertEquals((float) mRatingBar.getNumStars() / (int) (mRatingBar.getNumStars() / 1.5f),
+ mRatingBar.getStepSize());
- int currentMax = ratingBar.getMax();
- int currentProgress = ratingBar.getProgress();
- float currentStepSize = ratingBar.getStepSize();
+ final int currentMax = mRatingBar.getMax();
+ final int currentProgress = mRatingBar.getProgress();
+ final float currentStepSize = mRatingBar.getStepSize();
// exceptional value
- ratingBar.setStepSize(-1.5f);
- assertEquals(currentMax, ratingBar.getMax());
- assertEquals(currentProgress, ratingBar.getProgress());
- assertEquals(currentStepSize, ratingBar.getStepSize());
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setStepSize(-1.5f));
+ assertEquals(currentMax, mRatingBar.getMax());
+ assertEquals(currentProgress, mRatingBar.getProgress());
+ assertEquals(currentStepSize, mRatingBar.getStepSize());
- ratingBar.setStepSize(0f);
- assertEquals(currentMax, ratingBar.getMax());
- assertEquals(currentProgress, ratingBar.getProgress());
- assertEquals(currentStepSize, ratingBar.getStepSize());
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setStepSize(0f));
+ assertEquals(currentMax, mRatingBar.getMax());
+ assertEquals(currentProgress, mRatingBar.getProgress());
+ assertEquals(currentStepSize, mRatingBar.getStepSize());
- ratingBar.setStepSize(ratingBar.getNumStars() + 0.1f);
- assertEquals(currentMax, ratingBar.getMax());
- assertEquals(currentProgress, ratingBar.getProgress());
- assertEquals(currentStepSize, ratingBar.getStepSize());
+ mInstrumentation.runOnMainSync(
+ () -> mRatingBar.setStepSize(mRatingBar.getNumStars() + 0.1f));
+ assertEquals(currentMax, mRatingBar.getMax());
+ assertEquals(currentProgress, mRatingBar.getProgress());
+ assertEquals(currentStepSize, mRatingBar.getStepSize());
- ratingBar.setStepSize(Float.MAX_VALUE);
- assertEquals(currentMax, ratingBar.getMax());
- assertEquals(currentProgress, ratingBar.getProgress());
- assertEquals(currentStepSize, ratingBar.getStepSize());
- }
-
- /**
- * The listener interface for receiving OnRatingBarChangeListener events.
- * The class that is interested in processing a OnRatingBarChangeListener
- * event implements this interface, and the object created with that class
- * is registered with a component using the component's
- * <code>setOnRatingBarChangeListener<code> method. When
- * the OnRatingBarChangeListener event occurs, that object's appropriate
- * method is invoked.
- */
- private class MockOnRatingBarChangeListener implements OnRatingBarChangeListener {
- private boolean mCalledOnRatingChanged = false;
-
- boolean hasCalledOnRatingChanged() {
- return mCalledOnRatingChanged;
- }
-
- /*
- * (non-Javadoc)
- * @see android.widget.RadioGroup.OnRatingBarChangeListener#onRatingChanged
- * (RatingBar ratingBar, float rating, boolean fromTouch)
- */
- public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromTouch) {
- mCalledOnRatingChanged = true;
- }
-
- public void reset() {
- mCalledOnRatingChanged = false;
- }
- }
-
- /*
- * Mock class for ProgressBar to test protected methods
- */
- private class MockRatingBar extends RatingBar {
- public MockRatingBar(Context context) {
- super(context);
- }
-
- private boolean mCalledOnMeasure = false;
- private boolean mCalledRequestLayout = false;
-
- public boolean hasCalledOnMeasure() {
- return mCalledOnMeasure;
- }
-
- @Override
- protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- mCalledOnMeasure = true;
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
-
- public void requestLayout() {
- mCalledRequestLayout = true;
- super.requestLayout();
- }
-
- public boolean hasCalledRequestLayout() {
- return mCalledRequestLayout;
- }
-
- public void reset() {
- mCalledOnMeasure = false;
- mCalledRequestLayout = false;
- }
+ mInstrumentation.runOnMainSync(() -> mRatingBar.setStepSize(Float.MAX_VALUE));
+ assertEquals(currentMax, mRatingBar.getMax());
+ assertEquals(currentProgress, mRatingBar.getProgress());
+ assertEquals(currentStepSize, mRatingBar.getStepSize());
}
}
diff --git a/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java b/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java
index 2f3be6f..dfff694 100644
--- a/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java
@@ -16,6 +16,7 @@
package android.widget.cts;
+import android.app.Instrumentation;
import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -43,6 +44,7 @@
*/
public class RelativeLayoutTest extends
ActivityInstrumentationTestCase2<RelativeLayoutCtsActivity> {
+ private Instrumentation mInstrumentation;
private Activity mActivity;
public RelativeLayoutTest() {
@@ -52,6 +54,8 @@
@Override
protected void setUp() throws Exception {
super.setUp();
+
+ mInstrumentation = getInstrumentation();
mActivity = getActivity();
}
@@ -86,27 +90,19 @@
ViewAsserts.assertRightAligned(relativeLayout, view13);
relativeLayout.setIgnoreGravity(R.id.relative_view13);
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- relativeLayout.requestLayout();
- }
- });
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> relativeLayout.requestLayout());
+ mInstrumentation.waitForIdleSync();
ViewAsserts.assertRightAligned(relativeLayout, view12);
ViewAsserts.assertLeftAligned(relativeLayout, view13);
relativeLayout.setIgnoreGravity(0);
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- relativeLayout.requestLayout();
- }
- });
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> relativeLayout.requestLayout());
+ mInstrumentation.waitForIdleSync();
ViewAsserts.assertRightAligned(relativeLayout, view12);
ViewAsserts.assertRightAligned(relativeLayout, view13);
}
- public void testSetGravity() {
+ public void testAccessGravity() {
final RelativeLayout relativeLayout = (RelativeLayout) mActivity.findViewById(
R.id.relative_sublayout_gravity);
@@ -120,48 +116,38 @@
assertEquals(view11.getTop(), view10.getBottom());
// -- BOTTOM && RIGHT
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- relativeLayout.setGravity(Gravity.BOTTOM | Gravity.RIGHT);
- }
- });
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.runOnMainSync(
+ () -> relativeLayout.setGravity(Gravity.BOTTOM | Gravity.RIGHT));
+ mInstrumentation.waitForIdleSync();
+ assertEquals(Gravity.BOTTOM | Gravity.RIGHT, relativeLayout.getGravity());
ViewAsserts.assertRightAligned(relativeLayout, view10);
assertEquals(view11.getTop(), view10.getBottom());
ViewAsserts.assertRightAligned(relativeLayout, view11);
ViewAsserts.assertBottomAligned(relativeLayout, view11);
// -- BOTTOM
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- relativeLayout.setGravity(Gravity.BOTTOM);
- }
- });
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> relativeLayout.setGravity(Gravity.BOTTOM));
+ mInstrumentation.waitForIdleSync();
+ assertEquals(Gravity.BOTTOM | Gravity.START, relativeLayout.getGravity());
ViewAsserts.assertLeftAligned(relativeLayout, view10);
assertEquals(view11.getTop(), view10.getBottom());
ViewAsserts.assertLeftAligned(relativeLayout, view11);
ViewAsserts.assertBottomAligned(relativeLayout, view11);
// CENTER_HORIZONTAL
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- relativeLayout.setGravity(Gravity.CENTER_HORIZONTAL);
- }
- });
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> relativeLayout.setGravity(Gravity.CENTER_HORIZONTAL));
+ mInstrumentation.waitForIdleSync();
+ assertEquals(Gravity.CENTER_HORIZONTAL | Gravity.TOP,
+ relativeLayout.getGravity());
ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view10);
ViewAsserts.assertTopAligned(relativeLayout, view10);
ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view11);
assertEquals(view11.getTop(), view10.getBottom());
// CENTER_VERTICAL
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- relativeLayout.setGravity(Gravity.CENTER_VERTICAL);
- }
- });
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> relativeLayout.setGravity(Gravity.CENTER_VERTICAL));
+ mInstrumentation.waitForIdleSync();
+ assertEquals(Gravity.CENTER_VERTICAL | Gravity.START, relativeLayout.getGravity());
ViewAsserts.assertLeftAligned(relativeLayout, view10);
int topSpace = view10.getTop();
int bottomSpace = relativeLayout.getHeight() - view11.getBottom();
@@ -184,24 +170,20 @@
assertEquals(view11.getTop(), view10.getBottom());
// RIGHT
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- relativeLayout.setHorizontalGravity(Gravity.RIGHT);
- }
- });
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> relativeLayout.setHorizontalGravity(Gravity.RIGHT));
+ mInstrumentation.waitForIdleSync();
+ assertEquals(Gravity.RIGHT, Gravity.HORIZONTAL_GRAVITY_MASK & relativeLayout.getGravity());
ViewAsserts.assertRightAligned(relativeLayout, view10);
ViewAsserts.assertTopAligned(relativeLayout, view10);
ViewAsserts.assertRightAligned(relativeLayout, view11);
assertEquals(view11.getTop(), view10.getBottom());
// CENTER_HORIZONTAL
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- relativeLayout.setHorizontalGravity(Gravity.CENTER_HORIZONTAL);
- }
- });
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.runOnMainSync(
+ () -> relativeLayout.setHorizontalGravity(Gravity.CENTER_HORIZONTAL));
+ mInstrumentation.waitForIdleSync();
+ assertEquals(Gravity.CENTER_HORIZONTAL,
+ Gravity.HORIZONTAL_GRAVITY_MASK & relativeLayout.getGravity());
ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view10);
ViewAsserts.assertTopAligned(relativeLayout, view10);
ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view11);
@@ -222,24 +204,20 @@
assertEquals(view11.getTop(), view10.getBottom());
// BOTTOM
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- relativeLayout.setVerticalGravity(Gravity.BOTTOM);
- }
- });
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> relativeLayout.setVerticalGravity(Gravity.BOTTOM));
+ mInstrumentation.waitForIdleSync();
+ assertEquals(Gravity.BOTTOM, Gravity.VERTICAL_GRAVITY_MASK & relativeLayout.getGravity());
ViewAsserts.assertLeftAligned(relativeLayout, view10);
assertEquals(view11.getTop(), view10.getBottom());
ViewAsserts.assertLeftAligned(relativeLayout, view11);
ViewAsserts.assertBottomAligned(relativeLayout, view11);
// CENTER_VERTICAL
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- relativeLayout.setVerticalGravity(Gravity.CENTER_VERTICAL);
- }
- });
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.runOnMainSync(
+ () -> relativeLayout.setVerticalGravity(Gravity.CENTER_VERTICAL));
+ mInstrumentation.waitForIdleSync();
+ assertEquals(Gravity.CENTER_VERTICAL,
+ Gravity.VERTICAL_GRAVITY_MASK & relativeLayout.getGravity());
ViewAsserts.assertLeftAligned(relativeLayout, view10);
int topSpace = view10.getTop();
int bottomSpace = relativeLayout.getHeight() - view11.getBottom();
@@ -352,12 +330,9 @@
* Tests to prevent regressions in baseline alignment.
*/
public void testBaselineAlignment() {
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- mActivity.setContentView(R.layout.relative_layout_baseline);
- }
- });
- getInstrumentation().waitForIdleSync();
+ mInstrumentation.runOnMainSync(
+ () -> mActivity.setContentView(R.layout.relative_layout_baseline));
+ mInstrumentation.waitForIdleSync();
View button = mActivity.findViewById(R.id.button1);
assertTrue(button.getHeight() > 0);
diff --git a/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java
index 5706781..30f07da 100644
--- a/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java
@@ -16,26 +16,40 @@
package android.widget.cts;
-import android.widget.cts.R;
-
+import android.app.Activity;
+import android.content.res.XmlResourceParser;
import android.test.ActivityInstrumentationTestCase2;
import android.test.ViewAsserts;
import android.util.LayoutDirection;
import android.view.View;
+import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.RelativeLayout;
+import android.widget.cts.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
/**
* Test {@link RelativeLayout.LayoutParams}.
*/
public class RelativeLayout_LayoutParamsTest extends
ActivityInstrumentationTestCase2<RelativeLayoutCtsActivity> {
+ private Activity mActivity;
public RelativeLayout_LayoutParamsTest() {
super("android.widget.cts", RelativeLayoutCtsActivity.class);
}
- public void testConstructor() {
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mActivity = getActivity();
+ }
+
+ public void testConstructor() throws XmlPullParserException, IOException {
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(200, 300);
assertEquals(200, layoutParams.width);
@@ -46,22 +60,32 @@
assertEquals(200, layoutParams.width);
assertEquals(300, layoutParams.height);
+ ViewGroup.LayoutParams tempViewGroupLayoutParams = new ViewGroup.LayoutParams(300, 400);
+ layoutParams = new RelativeLayout.LayoutParams(tempViewGroupLayoutParams);
+ assertEquals(300, layoutParams.width);
+ assertEquals(400, layoutParams.height);
+
MarginLayoutParams tempMarginLayoutParams = new MarginLayoutParams(400, 500);
layoutParams = new RelativeLayout.LayoutParams(tempMarginLayoutParams);
assertEquals(400, layoutParams.width);
assertEquals(500, layoutParams.height);
+ XmlResourceParser p = mActivity.getResources().getLayout(R.layout.relative_layout);
+ XmlUtils.beginDocument(p, "RelativeLayout");
+ layoutParams = new RelativeLayout.LayoutParams(mActivity, p);
+ assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, layoutParams.width);
+ assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, layoutParams.height);
+
// Test RelativeLayout.Params which generated from the xml file.
int rules[];
- RelativeLayoutCtsActivity activity = getActivity();
// test attributes used in RelativeLayout.
- RelativeLayout relativeLayout = (RelativeLayout) activity.findViewById(
+ RelativeLayout relativeLayout = (RelativeLayout) mActivity.findViewById(
R.id.relative_sublayout_attrs);
// view1, centered within its parent.
// TEST: android:layout_centerInParent
- View view1 = activity.findViewById(R.id.relative_view1);
+ View view1 = mActivity.findViewById(R.id.relative_view1);
ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view1);
ViewAsserts.assertVerticalCenterAligned(relativeLayout, view1);
layoutParams = (RelativeLayout.LayoutParams) (view1.getLayoutParams());
@@ -70,7 +94,7 @@
// view2, below view1 and has same left position with view1.
// TEST: android:layout_below; android:layout_alignLeft
- View view2 = activity.findViewById(R.id.relative_view2);
+ View view2 = mActivity.findViewById(R.id.relative_view2);
ViewAsserts.assertLeftAligned(view1, view2);
assertEquals(view1.getBottom(), view2.getTop());
layoutParams = (RelativeLayout.LayoutParams) (view2.getLayoutParams());
@@ -81,7 +105,7 @@
// view3, has same top position with view1 and same bottom position with view2,
// and on the right of view1.1.
// TEST: android:layout_alignTop; android:layout_alignBottom; android:layout_toRightOf
- View view3 = activity.findViewById(R.id.relative_view3);
+ View view3 = mActivity.findViewById(R.id.relative_view3);
ViewAsserts.assertTopAligned(view1, view3);
ViewAsserts.assertBottomAligned(view2, view3);
assertEquals(view1.getRight(), view3.getLeft());
@@ -93,7 +117,7 @@
// view4, has same right position with view3 and above view3.
// TEST: android:layout_alignRight; android:layout_above
- View view4 = activity.findViewById(R.id.relative_view4);
+ View view4 = mActivity.findViewById(R.id.relative_view4);
ViewAsserts.assertRightAligned(view3, view4);
assertEquals(view3.getTop(), view4.getBottom());
layoutParams = (RelativeLayout.LayoutParams) (view4.getLayoutParams());
@@ -103,7 +127,7 @@
// view5 goes on the left-bottom.
// TEST: android:layout_alignParentBottom; android:layout_alignParentLeft
- View view5 = activity.findViewById(R.id.relative_view5);
+ View view5 = mActivity.findViewById(R.id.relative_view5);
ViewAsserts.assertLeftAligned(relativeLayout, view5);
ViewAsserts.assertBottomAligned(relativeLayout, view5);
layoutParams = (RelativeLayout.LayoutParams) (view5.getLayoutParams());
@@ -113,7 +137,7 @@
// view6 goes on the top-right.
// TEST: android:layout_alignParentTop; android:layout_alignParentRight
- View view6 = activity.findViewById(R.id.relative_view6);
+ View view6 = mActivity.findViewById(R.id.relative_view6);
ViewAsserts.assertTopAligned(relativeLayout, view6);
ViewAsserts.assertRightAligned(relativeLayout, view6);
layoutParams = (RelativeLayout.LayoutParams) (view6.getLayoutParams());
@@ -123,7 +147,7 @@
// view7, has same baseline with view6 and centered horizontally within its parent.
// TEST: android:layout_alignBaseline; android:layout_centerHorizontal
- View view7 = activity.findViewById(R.id.relative_view7);
+ View view7 = mActivity.findViewById(R.id.relative_view7);
ViewAsserts.assertBaselineAligned(view6, view7);
ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view7);
layoutParams = (RelativeLayout.LayoutParams) (view7.getLayoutParams());
@@ -133,7 +157,7 @@
// view8, centered vertically within its parent and on the left of view1.
// TEST: android:layout_toLeftOf; android:layout_centerVertical
- View view8 = activity.findViewById(R.id.relative_view8);
+ View view8 = mActivity.findViewById(R.id.relative_view8);
ViewAsserts.assertVerticalCenterAligned(relativeLayout, view8);
assertEquals(view1.getLeft(), view8.getRight());
layoutParams = (RelativeLayout.LayoutParams) (view8.getLayoutParams());
@@ -144,7 +168,7 @@
// view9, has same top and bottom position with view3 and same left position with its parent
// TEST: android:layout_alignLeft; android:layout_alignTop; android:layout_alignBottom;
// android:layout_alignWithParentIfMissing
- View view9 = activity.findViewById(R.id.relative_view9);
+ View view9 = mActivity.findViewById(R.id.relative_view9);
ViewAsserts.assertTopAligned(view3, view9);
ViewAsserts.assertBottomAligned(view3, view9);
ViewAsserts.assertLeftAligned(relativeLayout, view9);
@@ -160,15 +184,14 @@
// Test RelativeLayout.Params which generated from the xml file.
int rules[];
- RelativeLayoutCtsActivity activity = getActivity();
// test attributes used in RelativeLayout.
- RelativeLayout relativeLayout = (RelativeLayout) activity.findViewById(
+ RelativeLayout relativeLayout = (RelativeLayout) mActivity.findViewById(
R.id.relative_sublayout_attrs_2);
// view1, centered within its parent.
// TEST: android:layout_centerInParent
- View view1 = activity.findViewById(R.id.relative_view21);
+ View view1 = mActivity.findViewById(R.id.relative_view21);
ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view1);
ViewAsserts.assertVerticalCenterAligned(relativeLayout, view1);
layoutParams = (RelativeLayout.LayoutParams) (view1.getLayoutParams());
@@ -177,7 +200,7 @@
// view2, below view1 and has same left position with view1.
// TEST: android:layout_below; android:layout_alignStart
- View view2 = activity.findViewById(R.id.relative_view22);
+ View view2 = mActivity.findViewById(R.id.relative_view22);
ViewAsserts.assertLeftAligned(view1, view2);
assertEquals(view1.getBottom(), view2.getTop());
layoutParams = (RelativeLayout.LayoutParams) (view2.getLayoutParams());
@@ -197,7 +220,7 @@
// view3, has same top position with view1 and same bottom position with view2,
// and on the right of view1.1.
// TEST: android:layout_alignTop; android:layout_alignBottom; android:layout_toEndOf
- View view3 = activity.findViewById(R.id.relative_view23);
+ View view3 = mActivity.findViewById(R.id.relative_view23);
ViewAsserts.assertTopAligned(view1, view3);
ViewAsserts.assertBottomAligned(view2, view3);
assertEquals(view1.getRight(), view3.getLeft());
@@ -219,7 +242,7 @@
// view4, has same right position with view3 and above view3.
// TEST: android:layout_alignEnd; android:layout_above
- View view4 = activity.findViewById(R.id.relative_view24);
+ View view4 = mActivity.findViewById(R.id.relative_view24);
ViewAsserts.assertRightAligned(view3, view4);
assertEquals(view3.getTop(), view4.getBottom());
layoutParams = (RelativeLayout.LayoutParams) (view4.getLayoutParams());
@@ -238,7 +261,7 @@
// view5 goes on the left-bottom.
// TEST: android:layout_alignParentBottom; android:layout_alignParentStart
- View view5 = activity.findViewById(R.id.relative_view25);
+ View view5 = mActivity.findViewById(R.id.relative_view25);
ViewAsserts.assertLeftAligned(relativeLayout, view5);
ViewAsserts.assertBottomAligned(relativeLayout, view5);
layoutParams = (RelativeLayout.LayoutParams) (view5.getLayoutParams());
@@ -257,7 +280,7 @@
// view6 goes on the top-right.
// TEST: android:layout_alignParentTop; android:layout_alignParentEnd
- View view6 = activity.findViewById(R.id.relative_view26);
+ View view6 = mActivity.findViewById(R.id.relative_view26);
ViewAsserts.assertTopAligned(relativeLayout, view6);
ViewAsserts.assertRightAligned(relativeLayout, view6);
layoutParams = (RelativeLayout.LayoutParams) (view6.getLayoutParams());
@@ -276,7 +299,7 @@
// view7, has same baseline with view6 and centered horizontally within its parent.
// TEST: android:layout_alignBaseline; android:layout_centerHorizontal
- View view7 = activity.findViewById(R.id.relative_view27);
+ View view7 = mActivity.findViewById(R.id.relative_view27);
ViewAsserts.assertBaselineAligned(view6, view7);
ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view7);
layoutParams = (RelativeLayout.LayoutParams) (view7.getLayoutParams());
@@ -291,7 +314,7 @@
// view8, centered vertically within its parent and on the left of view1.
// TEST: android:layout_toStartOf; android:layout_centerVertical
- View view8 = activity.findViewById(R.id.relative_view28);
+ View view8 = mActivity.findViewById(R.id.relative_view28);
ViewAsserts.assertVerticalCenterAligned(relativeLayout, view8);
assertEquals(view1.getLeft(), view8.getRight());
layoutParams = (RelativeLayout.LayoutParams) (view8.getLayoutParams());
@@ -311,7 +334,7 @@
// view9, has same top and bottom position with view3 and same left position with its parent
// TEST: android:layout_alignStart; android:layout_alignTop; android:layout_alignBottom;
// android:layout_alignWithParentIfMissing
- View view9 = activity.findViewById(R.id.relative_view29);
+ View view9 = mActivity.findViewById(R.id.relative_view29);
ViewAsserts.assertTopAligned(view3, view9);
ViewAsserts.assertBottomAligned(view3, view9);
ViewAsserts.assertLeftAligned(relativeLayout, view9);
diff --git a/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java b/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
index 605dbb6..f3a04be 100644
--- a/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
@@ -17,8 +17,8 @@
package android.widget.cts;
import android.graphics.drawable.Icon;
+import android.os.Bundle;
import android.test.UiThreadTest;
-import android.widget.cts.R;
import android.app.Activity;
@@ -34,20 +34,34 @@
import android.net.Uri;
import android.os.Parcel;
import android.test.ActivityInstrumentationTestCase2;
+import android.text.TextUtils;
+import android.util.TypedValue;
import android.view.View;
import android.widget.AbsoluteLayout;
+import android.widget.AnalogClock;
+import android.widget.Button;
import android.widget.Chronometer;
+import android.widget.DatePicker;
+import android.widget.DateTimeView;
import android.widget.EditText;
import android.widget.FrameLayout;
+import android.widget.GridLayout;
import android.widget.GridView;
+import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
+import android.widget.NumberPicker;
import android.widget.ProgressBar;
+import android.widget.RatingBar;
import android.widget.RelativeLayout;
import android.widget.RemoteViews;
+import android.widget.SeekBar;
+import android.widget.StackView;
+import android.widget.TextClock;
import android.widget.TextView;
import android.widget.RemoteViews.ActionException;
+import android.widget.ViewFlipper;
import java.io.File;
import java.io.FileOutputStream;
@@ -61,16 +75,18 @@
public class RemoteViewsTest extends ActivityInstrumentationTestCase2<RemoteViewsCtsActivity> {
private static final String PACKAGE_NAME = "android.widget.cts";
- private static final int INVALD_ID = -1;
+ private static final int INVALID_ID = -1;
private static final long TEST_TIMEOUT = 5000;
+ private Instrumentation mInstrumentation;
+
+ private Activity mActivity;
+
private RemoteViews mRemoteViews;
private View mResult;
- private Activity mActivity;
-
public RemoteViewsTest() {
super(PACKAGE_NAME, RemoteViewsCtsActivity.class);
}
@@ -78,13 +94,12 @@
@Override
protected void setUp() throws Exception {
super.setUp();
+
+ mInstrumentation = getInstrumentation();
mActivity = getActivity();
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- mRemoteViews = new RemoteViews(PACKAGE_NAME, R.layout.remoteviews_good);
- mResult = mRemoteViews.apply(mActivity, null);
- }
+ mInstrumentation.runOnMainSync(() -> {
+ mRemoteViews = new RemoteViews(PACKAGE_NAME, R.layout.remoteviews_good);
+ mResult = mRemoteViews.apply(mActivity, null);
});
}
@@ -107,13 +122,24 @@
mRemoteViews = new RemoteViews(PACKAGE_NAME, R.layout.listview_layout);
assertEquals(R.layout.listview_layout, mRemoteViews.getLayoutId());
- mRemoteViews = new RemoteViews(PACKAGE_NAME, INVALD_ID);
- assertEquals(INVALD_ID, mRemoteViews.getLayoutId());
+ mRemoteViews = new RemoteViews(PACKAGE_NAME, INVALID_ID);
+ assertEquals(INVALID_ID, mRemoteViews.getLayoutId());
mRemoteViews = new RemoteViews(PACKAGE_NAME, 0);
assertEquals(0, mRemoteViews.getLayoutId());
}
+ public void testSetContentDescription() {
+ View view = mResult.findViewById(R.id.remoteView_frame);
+
+ assertNull(view.getContentDescription());
+
+ CharSequence contentDescription = mActivity.getString(R.string.remote_content_description);
+ mRemoteViews.setContentDescription(R.id.remoteView_frame, contentDescription);
+ mRemoteViews.reapply(mActivity, mResult);
+ assertTrue(TextUtils.equals(contentDescription, view.getContentDescription()));
+ }
+
public void testSetViewVisibility() {
View view = mResult.findViewById(R.id.remoteView_chronometer);
assertEquals(View.VISIBLE, view.getVisibility());
@@ -153,6 +179,23 @@
}
}
+ public void testSetTextViewTextSize() {
+ TextView textView = (TextView) mResult.findViewById(R.id.remoteView_text);
+
+ mRemoteViews.setTextViewTextSize(R.id.remoteView_text, TypedValue.COMPLEX_UNIT_SP, 18);
+ mRemoteViews.reapply(mActivity, mResult);
+ assertEquals(mActivity.getResources().getDisplayMetrics().scaledDensity * 18,
+ textView.getTextSize());
+
+ mRemoteViews.setTextViewTextSize(R.id.remoteView_absolute, TypedValue.COMPLEX_UNIT_SP, 20);
+ try {
+ mRemoteViews.reapply(mActivity, mResult);
+ fail("Should throw Throwable");
+ } catch (Throwable t) {
+ // expected
+ }
+ }
+
public void testSetIcon() {
ImageView image = (ImageView) mResult.findViewById(R.id.remoteView_image);
assertNull(image.getDrawable());
@@ -262,6 +305,26 @@
}
}
+ public void testSetChronometerCountDown() {
+ Chronometer chronometer = (Chronometer) mResult.findViewById(R.id.remoteView_chronometer);
+
+ mRemoteViews.setChronometerCountDown(R.id.remoteView_chronometer, true);
+ mRemoteViews.reapply(mActivity, mResult);
+ assertTrue(chronometer.isCountDown());
+
+ mRemoteViews.setChronometerCountDown(R.id.remoteView_chronometer, false);
+ mRemoteViews.reapply(mActivity, mResult);
+ assertFalse(chronometer.isCountDown());
+
+ mRemoteViews.setChronometerCountDown(R.id.remoteView_absolute, true);
+ try {
+ mRemoteViews.reapply(mActivity, mResult);
+ fail("Should throw ActionException");
+ } catch (ActionException e) {
+ // expected
+ }
+ }
+
public void testSetProgressBar() {
ProgressBar progress = (ProgressBar) mResult.findViewById(R.id.remoteView_progress);
assertEquals(100, progress.getMax());
@@ -305,7 +368,6 @@
}
public void testReapply() {
- TextView text = new TextView(mActivity);
ImageView image = (ImageView) mResult.findViewById(R.id.remoteView_image);
assertNull(image.getDrawable());
@@ -321,19 +383,31 @@
public void testOnLoadClass() {
mRemoteViews = new RemoteViews(Parcel.obtain());
- assertTrue(mRemoteViews.onLoadClass(RelativeLayout.class));
- assertTrue(mRemoteViews.onLoadClass(FrameLayout.class));
assertTrue(mRemoteViews.onLoadClass(AbsoluteLayout.class));
- assertTrue(mRemoteViews.onLoadClass(LinearLayout.class));
- assertTrue(mRemoteViews.onLoadClass(TextView.class));
- assertTrue(mRemoteViews.onLoadClass(ImageView.class));
- assertTrue(mRemoteViews.onLoadClass(ProgressBar.class));
+ assertTrue(mRemoteViews.onLoadClass(AnalogClock.class));
+ assertTrue(mRemoteViews.onLoadClass(Button.class));
assertTrue(mRemoteViews.onLoadClass(Chronometer.class));
- assertTrue(mRemoteViews.onLoadClass(ListView.class));
+ assertTrue(mRemoteViews.onLoadClass(DateTimeView.class));
+ assertTrue(mRemoteViews.onLoadClass(FrameLayout.class));
+ assertTrue(mRemoteViews.onLoadClass(GridLayout.class));
assertTrue(mRemoteViews.onLoadClass(GridView.class));
+ assertTrue(mRemoteViews.onLoadClass(ImageButton.class));
+ assertTrue(mRemoteViews.onLoadClass(ImageView.class));
+ assertTrue(mRemoteViews.onLoadClass(LinearLayout.class));
+ assertTrue(mRemoteViews.onLoadClass(ListView.class));
+ assertTrue(mRemoteViews.onLoadClass(ProgressBar.class));
+ assertTrue(mRemoteViews.onLoadClass(RelativeLayout.class));
+ assertTrue(mRemoteViews.onLoadClass(StackView.class));
+ assertTrue(mRemoteViews.onLoadClass(TextClock.class));
+ assertTrue(mRemoteViews.onLoadClass(TextView.class));
+ assertTrue(mRemoteViews.onLoadClass(ViewFlipper.class));
// those classes without annotation @RemoteView
assertFalse(mRemoteViews.onLoadClass(EditText.class));
+ assertFalse(mRemoteViews.onLoadClass(DatePicker.class));
+ assertFalse(mRemoteViews.onLoadClass(NumberPicker.class));
+ assertFalse(mRemoteViews.onLoadClass(RatingBar.class));
+ assertFalse(mRemoteViews.onLoadClass(SeekBar.class));
}
public void testDescribeContents() {
@@ -609,33 +683,106 @@
}
}
- public void testNotFeasibleSetters() {
- // there is no RemotableViewMethods to use them, how to test?
+ public void testSetByte() {
+ MyRemotableView customView = (MyRemotableView) mResult.findViewById(R.id.remoteView_custom);
+ assertEquals(0, customView.getByteField());
+
+ byte b = 100;
+ mRemoteViews.setByte(R.id.remoteView_custom, "setByteField", b);
+ mRemoteViews.reapply(mActivity, mResult);
+ assertEquals(b, customView.getByteField());
+
+ mRemoteViews.setByte(R.id.remoteView_absolute, "setByteField", b);
+ try {
+ mRemoteViews.reapply(mActivity, mResult);
+ fail("Should throw ActionException");
+ } catch (ActionException e) {
+ // expected
+ }
+ }
+
+ public void testSetChar() {
+ MyRemotableView customView = (MyRemotableView) mResult.findViewById(R.id.remoteView_custom);
+ assertEquals('\u0000', customView.getCharField());
+
+ mRemoteViews.setChar(R.id.remoteView_custom, "setCharField", 'q');
+ mRemoteViews.reapply(mActivity, mResult);
+ assertEquals('q', customView.getCharField());
+
+ mRemoteViews.setChar(R.id.remoteView_absolute, "setCharField", 'w');
+ try {
+ mRemoteViews.reapply(mActivity, mResult);
+ fail("Should throw ActionException");
+ } catch (ActionException e) {
+ // expected
+ }
+ }
+
+ public void testSetDouble() {
+ MyRemotableView customView = (MyRemotableView) mResult.findViewById(R.id.remoteView_custom);
+ assertEquals(0.0, customView.getDoubleField());
+
+ mRemoteViews.setDouble(R.id.remoteView_custom, "setDoubleField", 0.5);
+ mRemoteViews.reapply(mActivity, mResult);
+ assertEquals(0.5, customView.getDoubleField());
+
+ mRemoteViews.setDouble(R.id.remoteView_absolute, "setDoubleField", 1.0);
+ try {
+ mRemoteViews.reapply(mActivity, mResult);
+ fail("Should throw ActionException");
+ } catch (ActionException e) {
+ // expected
+ }
+ }
+
+ public void testSetShort() {
+ MyRemotableView customView = (MyRemotableView) mResult.findViewById(R.id.remoteView_custom);
+ assertEquals(0, customView.getShortField());
+
+ short s = 25;
+ mRemoteViews.setShort(R.id.remoteView_custom, "setShortField", s);
+ mRemoteViews.reapply(mActivity, mResult);
+ assertEquals(s, customView.getShortField());
+
+ mRemoteViews.setShort(R.id.remoteView_absolute, "setShortField", s);
+ try {
+ mRemoteViews.reapply(mActivity, mResult);
+ fail("Should throw ActionException");
+ } catch (ActionException e) {
+ // expected
+ }
+ }
+
+ public void testSetBundle() {
+ MyRemotableView customView = (MyRemotableView) mResult.findViewById(R.id.remoteView_custom);
+ assertNull(customView.getBundleField());
+
+ final Bundle bundle = new Bundle();
+ bundle.putString("STR", "brexit");
+ bundle.putInt("INT", 2016);
+ mRemoteViews.setBundle(R.id.remoteView_custom, "setBundleField", bundle);
+ mRemoteViews.reapply(mActivity, mResult);
+ Bundle fromRemote = customView.getBundleField();
+ assertEquals("brexit", fromRemote.getString("STR", ""));
+ assertEquals(2016, fromRemote.getInt("INT", 0));
+
+ mRemoteViews.setBundle(R.id.remoteView_absolute, "setBundleField", bundle);
+ try {
+ mRemoteViews.reapply(mActivity, mResult);
+ fail("Should throw ActionException");
+ } catch (ActionException e) {
+ // expected
+ }
}
private void createSampleImage(File imagefile, int resid) throws IOException {
- InputStream source = null;
- OutputStream target = null;
-
- try {
- source = mActivity.getResources().openRawResource(resid);
- target = new FileOutputStream(imagefile);
+ try (InputStream source = mActivity.getResources().openRawResource(resid);
+ OutputStream target = new FileOutputStream(imagefile)) {
byte[] buffer = new byte[1024];
for (int len = source.read(buffer); len > 0; len = source.read(buffer)) {
target.write(buffer, 0, len);
}
- } finally {
- try {
- if (source != null) {
- source.close();
- }
- if (target != null) {
- target.close();
- }
- } catch (IOException ignored) {
- // Ignore the IOException.
- }
}
}
}
diff --git a/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java b/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
index 26510f27..aec6cf2 100644
--- a/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
@@ -24,6 +24,7 @@
import android.widget.cts.R;
+import android.widget.cts.util.TestUtils;
import org.xmlpull.v1.XmlPullParser;
import android.app.Activity;
@@ -75,11 +76,10 @@
mScrollView = (MyScrollView) mActivity.findViewById(R.id.scroll_view);
// calculate pixel positions from dpi constants.
- final float density = getActivity().getResources().getDisplayMetrics().density;
- mItemWidth = (int) (ITEM_WIDTH_DPI * density + 0.5f);
- mItemHeight = (int) (ITEM_HEIGHT_DPI * density + 0.5f);
- mPageWidth = (int) (PAGE_WIDTH_DPI * density + 0.5f);
- mPageHeight = (int) (PAGE_HEIGHT_DPI * density + 0.5f);
+ mItemWidth = TestUtils.dpToPx(mActivity, ITEM_WIDTH_DPI);
+ mItemHeight = TestUtils.dpToPx(mActivity, ITEM_HEIGHT_DPI);
+ mPageWidth = TestUtils.dpToPx(mActivity, PAGE_WIDTH_DPI);
+ mPageHeight = TestUtils.dpToPx(mActivity, PAGE_HEIGHT_DPI);
mScrollBottom = mItemHeight * ITEM_COUNT - mPageHeight;
mScrollRight = mItemWidth - mPageWidth;
@@ -829,55 +829,34 @@
}
if (fromY != toY) {
- new PollingCheck() {
- @Override
- protected boolean check() {
- return isInRange(mScrollView.getScrollY(), fromY, toY);
- }
- }.run();
+ PollingCheck.waitFor(() -> isInRange(mScrollView.getScrollY(), fromY, toY));
}
if (fromX != toX) {
- new PollingCheck() {
- @Override
- protected boolean check() {
- return isInRange(mScrollView.getScrollX(), fromX, toX);
- }
- }.run();
+ PollingCheck.waitFor(() -> isInRange(mScrollView.getScrollX(), fromX, toX));
}
- new PollingCheck() {
- @Override
- protected boolean check() {
- return toX == mScrollView.getScrollX() && toY == mScrollView.getScrollY();
- }
- }.run();
+ PollingCheck.waitFor(
+ () -> toX == mScrollView.getScrollX() && toY == mScrollView.getScrollY());
}
private void pollingCheckFling(final int startPosition, final boolean movingDown) {
- new PollingCheck() {
- @Override
- protected boolean check() {
- if (movingDown) {
- return mScrollView.getScrollY() > startPosition;
- }
- return mScrollView.getScrollY() < startPosition;
+ PollingCheck.waitFor(() -> {
+ if (movingDown) {
+ return mScrollView.getScrollY() > startPosition;
}
- };
+ return mScrollView.getScrollY() < startPosition;
+ });
- new PollingCheck() {
- private int mPreviousScrollY = mScrollView.getScrollY();
-
- @Override
- protected boolean check() {
- if (mScrollView.getScrollY() == mPreviousScrollY) {
- return true;
- } else {
- mPreviousScrollY = mScrollView.getScrollY();
- return false;
- }
+ final int[] previousScrollY = new int[] { mScrollView.getScrollY() };
+ PollingCheck.waitFor(() -> {
+ if (mScrollView.getScrollY() == previousScrollY[0]) {
+ return true;
+ } else {
+ previousScrollY[0] = mScrollView.getScrollY();
+ return false;
}
- }.run();
+ });
}
public static class MyView extends View {
diff --git a/tests/tests/widget/src/android/widget/cts/SearchViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/SearchViewCtsActivity.java
new file mode 100644
index 0000000..5da8a32
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/SearchViewCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.SearchView;
+
+/**
+ * A minimal application for {@link SearchView} test.
+ */
+public class SearchViewCtsActivity extends Activity {
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.searchview_layout);
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/SearchViewTest.java b/tests/tests/widget/src/android/widget/cts/SearchViewTest.java
new file mode 100644
index 0000000..1701a8c
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/SearchViewTest.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.res.Resources;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.text.InputType;
+import android.text.TextUtils;
+import android.view.inputmethod.EditorInfo;
+import android.widget.SearchView;
+
+import static org.mockito.Mockito.*;
+
+/**
+ * Test {@link SearchView}.
+ */
+@MediumTest
+public class SearchViewTest extends ActivityInstrumentationTestCase2<SearchViewCtsActivity> {
+ private Instrumentation mInstrumentation;
+ private Activity mActivity;
+ private SearchView mSearchView;
+
+ public SearchViewTest() {
+ super("android.widget.cts", SearchViewCtsActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mInstrumentation = getInstrumentation();
+ mActivity = getActivity();
+ mSearchView = (SearchView) mActivity.findViewById(R.id.search_view);
+ }
+
+ @UiThreadTest
+ public void testConstructor() {
+ new SearchView(mActivity);
+
+ new SearchView(mActivity, null);
+
+ new SearchView(mActivity, null, android.R.attr.searchViewStyle);
+
+ new SearchView(mActivity, null, 0, android.R.style.Widget_Material_SearchView);
+
+ new SearchView(mActivity, null, 0, android.R.style.Widget_Material_Light_SearchView);
+ }
+
+ @UiThreadTest
+ public void testAttributesFromXml() {
+ SearchView searchViewWithAttributes =
+ (SearchView) mActivity.findViewById(R.id.search_view_with_defaults);
+ assertEquals(mActivity.getString(R.string.search_query_hint),
+ searchViewWithAttributes.getQueryHint());
+ assertFalse(searchViewWithAttributes.isIconfiedByDefault());
+ assertEquals(EditorInfo.TYPE_TEXT_FLAG_CAP_CHARACTERS | EditorInfo.TYPE_CLASS_TEXT,
+ searchViewWithAttributes.getInputType());
+ assertEquals(EditorInfo.IME_ACTION_DONE, searchViewWithAttributes.getImeOptions());
+ assertEquals(mActivity.getResources().getDimensionPixelSize(R.dimen.search_view_max_width),
+ searchViewWithAttributes.getMaxWidth());
+ }
+
+ public void testAccessIconified() {
+ mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(true));
+ assertTrue(mSearchView.isIconified());
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(false));
+ assertFalse(mSearchView.isIconified());
+ }
+
+ public void testAccessIconifiedByDefault() {
+ mInstrumentation.runOnMainSync(() -> mSearchView.setIconifiedByDefault(true));
+ assertTrue(mSearchView.isIconfiedByDefault());
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setIconifiedByDefault(false));
+ assertFalse(mSearchView.isIconfiedByDefault());
+ }
+
+ public void testDenyIconifyingNonInconifiableView() {
+ mInstrumentation.runOnMainSync(() -> {
+ mSearchView.setIconifiedByDefault(false);
+ mSearchView.setIconified(false);
+ });
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(true));
+ mInstrumentation.waitForIdleSync();
+
+ // Since our search view is marked with iconifiedByDefault=false, call to setIconified
+ // with true us going to be ignored, as detailed in the class-level documentation of
+ // SearchView.
+ assertFalse(mSearchView.isIconified());
+ }
+
+ public void testDenyIconifyingInconifiableView() {
+ mInstrumentation.runOnMainSync(() -> {
+ mSearchView.setIconifiedByDefault(true);
+ mSearchView.setIconified(false);
+ });
+
+ final SearchView.OnCloseListener mockDenyCloseListener =
+ mock(SearchView.OnCloseListener.class);
+ when(mockDenyCloseListener.onClose()).thenReturn(Boolean.TRUE);
+ mSearchView.setOnCloseListener(mockDenyCloseListener);
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(true));
+ mInstrumentation.waitForIdleSync();
+
+ // Our mock listener is configured to return true from its onClose, thereby preventing
+ // the iconify request to be completed. Check that the listener was called and that the
+ // search view is not iconified.
+ verify(mockDenyCloseListener, times(1)).onClose();
+ assertFalse(mSearchView.isIconified());
+ }
+
+ public void testAllowIconifyingInconifiableView() {
+ mInstrumentation.runOnMainSync(() -> {
+ mSearchView.setIconifiedByDefault(true);
+ mSearchView.setIconified(false);
+ });
+
+ final SearchView.OnCloseListener mockAllowCloseListener =
+ mock(SearchView.OnCloseListener.class);
+ when(mockAllowCloseListener.onClose()).thenReturn(Boolean.FALSE);
+ mSearchView.setOnCloseListener(mockAllowCloseListener);
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(true));
+ mInstrumentation.waitForIdleSync();
+
+ // Our mock listener is configured to return false from its onClose, thereby allowing
+ // the iconify request to be completed. Check that the listener was called and that the
+ // search view is not iconified.
+ verify(mockAllowCloseListener, times(1)).onClose();
+ assertTrue(mSearchView.isIconified());
+ }
+
+ public void testAccessMaxWidth() {
+ final Resources res = mActivity.getResources();
+ final int maxWidth1 = res.getDimensionPixelSize(R.dimen.search_view_max_width);
+ final int maxWidth2 = res.getDimensionPixelSize(R.dimen.search_view_max_width2);
+
+ // Set search view to not be iconified before running max-width tests
+ mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(false));
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setMaxWidth(maxWidth1));
+ mInstrumentation.waitForIdleSync();
+ assertEquals(maxWidth1, mSearchView.getMaxWidth());
+ assertTrue(mSearchView.getWidth() <= maxWidth1);
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setMaxWidth(maxWidth2));
+ mInstrumentation.waitForIdleSync();
+ assertEquals(maxWidth2, mSearchView.getMaxWidth());
+ assertTrue(mSearchView.getWidth() <= maxWidth2);
+ }
+
+ public void testAccessQuery() {
+ mInstrumentation.runOnMainSync(() -> mSearchView.setIconified(false));
+
+ final SearchView.OnQueryTextListener mockQueryTextListener =
+ mock(SearchView.OnQueryTextListener.class);
+ when(mockQueryTextListener.onQueryTextSubmit(anyString())).thenReturn(Boolean.TRUE);
+ mSearchView.setOnQueryTextListener(mockQueryTextListener);
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("alpha", false));
+ assertTrue(TextUtils.equals("alpha", mSearchView.getQuery()));
+ // Since we passed false as the second parameter to setQuery, our query text listener
+ // should have been invoked only with text change
+ verify(mockQueryTextListener, times(1)).onQueryTextChange("alpha");
+ verify(mockQueryTextListener, never()).onQueryTextSubmit(anyString());
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("beta", true));
+ assertTrue(TextUtils.equals("beta", mSearchView.getQuery()));
+ // Since we passed true as the second parameter to setQuery, our query text listener
+ // should have been invoked on both callbacks
+ verify(mockQueryTextListener, times(1)).onQueryTextChange("beta");
+ verify(mockQueryTextListener, times(1)).onQueryTextSubmit("beta");
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("gamma", true));
+ assertTrue(TextUtils.equals("gamma", mSearchView.getQuery()));
+ // Since we passed true as the second parameter to setQuery, our query text listener
+ // should have been invoked on both callbacks
+ verify(mockQueryTextListener, times(1)).onQueryTextChange("gamma");
+ verify(mockQueryTextListener, times(1)).onQueryTextSubmit("gamma");
+
+ verifyNoMoreInteractions(mockQueryTextListener);
+ }
+
+ public void testAccessQueryHint() {
+ mInstrumentation.runOnMainSync(() -> mSearchView.setQueryHint("hint 1"));
+ assertTrue(TextUtils.equals("hint 1", mSearchView.getQueryHint()));
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setQueryHint("hint 2"));
+ assertTrue(TextUtils.equals("hint 2", mSearchView.getQueryHint()));
+ }
+
+ public void testAccessInputType() {
+ mInstrumentation.runOnMainSync(() ->
+ mSearchView.setInputType(InputType.TYPE_CLASS_NUMBER
+ | InputType.TYPE_NUMBER_FLAG_DECIMAL
+ | InputType.TYPE_NUMBER_FLAG_SIGNED));
+ assertEquals(InputType.TYPE_CLASS_NUMBER
+ | InputType.TYPE_NUMBER_FLAG_DECIMAL
+ | InputType.TYPE_NUMBER_FLAG_SIGNED, mSearchView.getInputType());
+
+ mInstrumentation.runOnMainSync(() ->
+ mSearchView.setInputType(InputType.TYPE_CLASS_TEXT
+ | InputType.TYPE_TEXT_FLAG_CAP_WORDS));
+ assertEquals(InputType.TYPE_CLASS_TEXT
+ | InputType.TYPE_TEXT_FLAG_CAP_WORDS, mSearchView.getInputType());
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setInputType(InputType.TYPE_CLASS_PHONE));
+ assertEquals(InputType.TYPE_CLASS_PHONE, mSearchView.getInputType());
+ }
+
+ public void testAccessImeOptions() {
+ mInstrumentation.runOnMainSync(() -> mSearchView.setImeOptions(EditorInfo.IME_ACTION_GO));
+ assertEquals(EditorInfo.IME_ACTION_GO, mSearchView.getImeOptions());
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setImeOptions(EditorInfo.IME_ACTION_DONE));
+ assertEquals(EditorInfo.IME_ACTION_DONE, mSearchView.getImeOptions());
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setImeOptions(EditorInfo.IME_NULL));
+ assertEquals(EditorInfo.IME_NULL, mSearchView.getImeOptions());
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/SearchView_CursorTest.java b/tests/tests/widget/src/android/widget/cts/SearchView_CursorTest.java
new file mode 100644
index 0000000..5b8dbfc
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/SearchView_CursorTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.cts.util.PollingCheck;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.provider.BaseColumns;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.text.TextUtils;
+import android.widget.CursorAdapter;
+import android.widget.SearchView;
+import android.widget.SimpleCursorAdapter;
+import android.widget.cts.util.ViewTestUtils;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.*;
+
+/**
+ * Test {@link SearchView} with {@link Cursor}-backed suggestions adapter.
+ */
+@MediumTest
+public class SearchView_CursorTest extends ActivityInstrumentationTestCase2<SearchViewCtsActivity> {
+ private Instrumentation mInstrumentation;
+ private Activity mActivity;
+ private SearchView mSearchView;
+
+ private static final String TEXT_COLUMN_NAME = "text";
+ private String[] mTextContent;
+
+ private CursorAdapter mSuggestionsAdapter;
+
+ protected class MyQueryTextListener implements SearchView.OnQueryTextListener {
+ @Override
+ public boolean onQueryTextSubmit(String s) {
+ return false;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String s) {
+ if (mSuggestionsAdapter == null) {
+ return false;
+ }
+
+ final MatrixCursor c = new MatrixCursor(
+ new String[] { BaseColumns._ID, TEXT_COLUMN_NAME} );
+ for (int i = 0; i < mTextContent.length; i++) {
+ if (mTextContent[i].toLowerCase().startsWith(s.toLowerCase())) {
+ c.addRow(new Object[]{i, mTextContent[i]});
+ }
+ }
+ mSuggestionsAdapter.swapCursor(c);
+ return false;
+ }
+ }
+
+ protected class MySuggestionListener implements SearchView.OnSuggestionListener {
+ @Override
+ public boolean onSuggestionSelect(int position) {
+ return false;
+ }
+
+ @Override
+ public boolean onSuggestionClick(int position) {
+ if (mSuggestionsAdapter != null) {
+ final Cursor cursor = mSuggestionsAdapter.getCursor();
+ if (cursor != null) {
+ cursor.moveToPosition(position);
+ mSearchView.setQuery(cursor.getString(1), false);
+ }
+ }
+ return false;
+ }
+ }
+
+ public SearchView_CursorTest() {
+ super("android.widget.cts", SearchViewCtsActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mInstrumentation = getInstrumentation();
+ mActivity = getActivity();
+ mSearchView = (SearchView) mActivity.findViewById(R.id.search_view);
+
+ // Local test data for the tests
+ mTextContent = new String[] { "Akon", "Bono", "Ciara", "Dido", "Diplo" };
+
+ mInstrumentation.runOnMainSync(() -> {
+ // Use an adapter with our custom layout for each entry. The adapter "maps"
+ // the content of the text column of our cursor to the @id/text1 view in the
+ // layout.
+ mSuggestionsAdapter = new SimpleCursorAdapter(
+ mActivity,
+ R.layout.searchview_suggestion_item,
+ null,
+ new String[] { TEXT_COLUMN_NAME },
+ new int[] { android.R.id.text1 },
+ CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
+ mSearchView.setSuggestionsAdapter(mSuggestionsAdapter);
+ });
+ }
+
+ public void testSuggestionFiltering() {
+ final SearchView.OnQueryTextListener mockQueryTextListener =
+ spy(new MyQueryTextListener());
+ when(mockQueryTextListener.onQueryTextChange(anyString())).thenCallRealMethod();
+
+ mInstrumentation.runOnMainSync(() -> {
+ mSearchView.setIconifiedByDefault(false);
+ mSearchView.setOnQueryTextListener(mockQueryTextListener);
+ mSearchView.requestFocus();
+ });
+
+ assertTrue(mSearchView.hasFocus());
+ assertEquals(mSuggestionsAdapter, mSearchView.getSuggestionsAdapter());
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("Bon", false));
+ verify(mockQueryTextListener, times(1)).onQueryTextChange("Bon");
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("Di", false));
+ verify(mockQueryTextListener, times(1)).onQueryTextChange("Di");
+ }
+
+ public void testSuggestionSelection() {
+ final SearchView.OnSuggestionListener mockSuggestionListener =
+ spy(new MySuggestionListener());
+ when(mockSuggestionListener.onSuggestionClick(anyInt())).thenCallRealMethod();
+
+ final SearchView.OnQueryTextListener mockQueryTextListener =
+ spy(new MyQueryTextListener());
+ when(mockQueryTextListener.onQueryTextChange(anyString())).thenCallRealMethod();
+
+ mInstrumentation.runOnMainSync(() -> {
+ mSearchView.setIconifiedByDefault(false);
+ mSearchView.setOnQueryTextListener(mockQueryTextListener);
+ mSearchView.setOnSuggestionListener(mockSuggestionListener);
+ mSearchView.requestFocus();
+ });
+
+ assertTrue(mSearchView.hasFocus());
+ assertEquals(mSuggestionsAdapter, mSearchView.getSuggestionsAdapter());
+
+ mInstrumentation.runOnMainSync(() -> mSearchView.setQuery("Di", false));
+ mInstrumentation.waitForIdleSync();
+ verify(mockQueryTextListener, times(1)).onQueryTextChange("Di");
+
+ // Emulate click on the first suggestion - which should be Dido
+ final int suggestionRowHeight = mActivity.getResources().getDimensionPixelSize(
+ R.dimen.search_view_suggestion_row_height);
+ ViewTestUtils.emulateTapOnScreen(mInstrumentation, mSearchView, mSearchView.getWidth() / 2,
+ mSearchView.getHeight() + suggestionRowHeight / 2);
+
+ // At this point we expect the click on the first suggestion to have activated a sequence
+ // of events that ends up in our suggestion listener that sets the full suggestion text
+ // as the current query. Some parts of this sequence of events are asynchronous, and those
+ // are not "caught" by Instrumentation.waitForIdleSync - which is in general not a very
+ // reliable way to wait for everything to be completed. As such, we are using our own
+ // polling check mechanism to wait until the search view's query is the fully completed
+ // suggestion for Dido. This check will time out and fail after a few seconds if anything
+ // goes wrong during the processing of the emulated tap and the code never gets to our
+ // suggestion listener
+ PollingCheck.waitFor(() -> TextUtils.equals("Dido", mSearchView.getQuery()));
+
+ // Just to be sure, verify that our spy suggestion listener was called
+ verify(mockSuggestionListener, times(1)).onSuggestionClick(0);
+ verifyNoMoreInteractions(mockSuggestionListener);
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/SeekBarCtsActivity.java b/tests/tests/widget/src/android/widget/cts/SeekBarCtsActivity.java
index e22b910..5dcbe56 100644
--- a/tests/tests/widget/src/android/widget/cts/SeekBarCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/SeekBarCtsActivity.java
@@ -16,8 +16,6 @@
package android.widget.cts;
-import android.widget.cts.R;
-
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
@@ -28,7 +26,7 @@
*/
public class SeekBarCtsActivity extends Activity {
/**
- * Called with the activity is first created.
+ * Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
diff --git a/tests/tests/widget/src/android/widget/cts/SeekBarTest.java b/tests/tests/widget/src/android/widget/cts/SeekBarTest.java
index b9ad733..fa47940 100644
--- a/tests/tests/widget/src/android/widget/cts/SeekBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SeekBarTest.java
@@ -16,20 +16,20 @@
package android.widget.cts;
-import android.widget.cts.R;
-
-
import android.app.Activity;
import android.app.Instrumentation;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
import android.view.MotionEvent;
import android.widget.SeekBar;
-import android.widget.SeekBar.OnSeekBarChangeListener;
+
+import static org.mockito.Mockito.*;
/**
* Test {@link SeekBar}.
*/
+@SmallTest
public class SeekBarTest extends ActivityInstrumentationTestCase2<SeekBarCtsActivity> {
private SeekBar mSeekBar;
@@ -55,13 +55,21 @@
new SeekBar(mActivity, null);
new SeekBar(mActivity, null, android.R.attr.seekBarStyle);
+
+ new SeekBar(mActivity, null, 0, android.R.style.Widget_DeviceDefault_SeekBar);
+
+ new SeekBar(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_SeekBar);
+
+ new SeekBar(mActivity, null, 0, android.R.style.Widget_Material_SeekBar);
+
+ new SeekBar(mActivity, null, 0, android.R.style.Widget_Material_Light_SeekBar);
}
public void testSetOnSeekBarChangeListener() {
- MockOnSeekBarListener listener = new MockOnSeekBarListener();
+ SeekBar.OnSeekBarChangeListener mockChangeListener =
+ mock(SeekBar.OnSeekBarChangeListener.class);
- mSeekBar.setOnSeekBarChangeListener(listener);
- listener.reset();
+ mSeekBar.setOnSeekBarChangeListener(mockChangeListener);
long downTime = SystemClock.uptimeMillis();
long eventTime = SystemClock.uptimeMillis();
int seekBarXY[] = new int[2];
@@ -70,66 +78,28 @@
seekBarXY[0], seekBarXY[1], 0);
mInstrumentation.sendPointerSync(event);
mInstrumentation.waitForIdleSync();
- assertTrue(listener.hasCalledOnStartTrackingTouch());
+ verify(mockChangeListener, times(1)).onStartTrackingTouch(mSeekBar);
// while starting to track, the progress is changed also
- assertTrue(listener.hasCalledOnProgressChanged());
+ verify(mockChangeListener, atLeastOnce()).onProgressChanged(eq(mSeekBar), anyInt(),
+ eq(true));
- listener.reset();
+ reset(mockChangeListener);
downTime = SystemClock.uptimeMillis();
eventTime = SystemClock.uptimeMillis();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE,
seekBarXY[0] + (mSeekBar.getWidth() >> 1), seekBarXY[1], 0);
mInstrumentation.sendPointerSync(event);
mInstrumentation.waitForIdleSync();
- assertTrue(listener.hasCalledOnProgressChanged());
+ verify(mockChangeListener, atLeastOnce()).onProgressChanged(eq(mSeekBar), anyInt(),
+ eq(true));
- listener.reset();
+ reset(mockChangeListener);
downTime = SystemClock.uptimeMillis();
eventTime = SystemClock.uptimeMillis();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP,
seekBarXY[0] + (mSeekBar.getWidth() >> 1), seekBarXY[1], 0);
mInstrumentation.sendPointerSync(event);
mInstrumentation.waitForIdleSync();
- assertTrue(listener.hasCalledOnStopTrackingTouch());
-
- mSeekBar.setOnSeekBarChangeListener(null);
- }
-
- private class MockOnSeekBarListener implements OnSeekBarChangeListener {
- private boolean mHasCalledOnProgressChanged;
-
- private boolean mHasCalledOnStartTrackingTouch;
-
- private boolean mHasCalledOnStopTrackingTouch;
-
- public boolean hasCalledOnProgressChanged() {
- return mHasCalledOnProgressChanged;
- }
-
- public boolean hasCalledOnStartTrackingTouch() {
- return mHasCalledOnStartTrackingTouch;
- }
-
- public boolean hasCalledOnStopTrackingTouch() {
- return mHasCalledOnStopTrackingTouch;
- }
-
- public void reset(){
- mHasCalledOnProgressChanged = false;
- mHasCalledOnStartTrackingTouch = false;
- mHasCalledOnStopTrackingTouch = false;
- }
-
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
- mHasCalledOnProgressChanged = true;
- }
-
- public void onStartTrackingTouch(SeekBar seekBar) {
- mHasCalledOnStartTrackingTouch = true;
- }
-
- public void onStopTrackingTouch(SeekBar seekBar) {
- mHasCalledOnStopTrackingTouch = true;
- }
+ verify(mockChangeListener, times(1)).onStopTrackingTouch(mSeekBar);
}
}
diff --git a/tests/tests/widget/src/android/widget/cts/SlidingDrawerTest.java b/tests/tests/widget/src/android/widget/cts/SlidingDrawerTest.java
index 2af1b06..efed9e8 100644
--- a/tests/tests/widget/src/android/widget/cts/SlidingDrawerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SlidingDrawerTest.java
@@ -16,29 +16,27 @@
package android.widget.cts;
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.app.Activity;
-import android.content.Context;
import android.cts.util.PollingCheck;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
import android.util.AttributeSet;
import android.util.Xml;
-import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.SlidingDrawer;
import android.widget.TextView;
-import android.widget.SlidingDrawer.OnDrawerCloseListener;
-import android.widget.SlidingDrawer.OnDrawerOpenListener;
-import android.widget.SlidingDrawer.OnDrawerScrollListener;
+
+import org.mockito.InOrder;
+import org.mockito.invocation.InvocationOnMock;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.mockito.Mockito.*;
/**
* Test {@link SlidingDrawer}.
@@ -48,7 +46,6 @@
private static final long TEST_TIMEOUT = 5000L;
private Activity mActivity;
- private Object mLock;
public SlidingDrawerTest() {
super("android.widget.cts", SlidingDrawerCtsActivity.class);
@@ -58,7 +55,6 @@
protected void setUp() throws Exception {
super.setUp();
mActivity = getActivity();
- mLock = new Object();
}
@UiThreadTest
@@ -118,40 +114,20 @@
assertFalse(drawer.isOpened());
assertEquals(View.GONE, content.getVisibility());
- runTestOnUiThread(new Runnable() {
- public void run() {
- drawer.animateOpen();
- }
- });
+ runTestOnUiThread(() -> drawer.animateOpen());
assertTrue(drawer.isMoving());
- assertOpened(false, drawer);
assertEquals(View.GONE, content.getVisibility());
- new PollingCheck() {
- @Override
- protected boolean check() {
- return !drawer.isMoving();
- }
- }.run();
- assertOpened(true, drawer);
+ PollingCheck.waitFor(() -> !drawer.isMoving());
+ PollingCheck.waitFor(() -> drawer.isOpened());
assertEquals(View.VISIBLE, content.getVisibility());
- runTestOnUiThread(new Runnable() {
- public void run() {
- drawer.animateClose();
- }
- });
+ runTestOnUiThread(() -> drawer.animateClose());
assertTrue(drawer.isMoving());
- assertOpened(true, drawer);
assertEquals(View.GONE, content.getVisibility());
- new PollingCheck() {
- @Override
- protected boolean check() {
- return !drawer.isMoving();
- }
- }.run();
- assertOpened(false, drawer);
+ PollingCheck.waitFor(() -> !drawer.isMoving());
+ PollingCheck.waitFor(() -> !drawer.isOpened());
assertEquals(View.GONE, content.getVisibility());
}
@@ -162,52 +138,23 @@
assertFalse(drawer.isOpened());
assertEquals(View.GONE, content.getVisibility());
- runTestOnUiThread(new Runnable() {
- public void run() {
- drawer.animateToggle();
- }
- });
+ runTestOnUiThread(() -> drawer.animateToggle());
assertTrue(drawer.isMoving());
- assertOpened(false, drawer);
assertEquals(View.GONE, content.getVisibility());
- new PollingCheck() {
- @Override
- protected boolean check() {
- return !drawer.isMoving();
- }
- }.run();
- assertOpened(true, drawer);
+ PollingCheck.waitFor(() -> !drawer.isMoving());
+ PollingCheck.waitFor(() -> drawer.isOpened());
assertEquals(View.VISIBLE, content.getVisibility());
- runTestOnUiThread(new Runnable() {
- public void run() {
- drawer.animateToggle();
- }
- });
+ runTestOnUiThread(() -> drawer.animateToggle());
assertTrue(drawer.isMoving());
- assertOpened(true, drawer);
assertEquals(View.GONE, content.getVisibility());
- new PollingCheck() {
- @Override
- protected boolean check() {
- return !drawer.isMoving();
- }
- }.run();
- assertOpened(false, drawer);
+ PollingCheck.waitFor(() -> !drawer.isMoving());
+ PollingCheck.waitFor(() -> !drawer.isOpened());
assertEquals(View.GONE, content.getVisibility());
}
- private void assertOpened(final boolean opened, final SlidingDrawer drawer) {
- new PollingCheck() {
- @Override
- protected boolean check() {
- return drawer.isOpened() == opened;
- }
- }.run();
- }
-
@UiThreadTest
public void testToggle() {
SlidingDrawer drawer = (SlidingDrawer) mActivity.findViewById(R.id.drawer);
@@ -254,56 +201,61 @@
@UiThreadTest
public void testSetOnDrawerOpenListener() {
SlidingDrawer drawer = (SlidingDrawer) mActivity.findViewById(R.id.drawer);
- MockOnDrawerOpenListener listener = new MockOnDrawerOpenListener();
- drawer.setOnDrawerOpenListener(listener);
+ SlidingDrawer.OnDrawerOpenListener mockOpenListener =
+ mock(SlidingDrawer.OnDrawerOpenListener.class);
+ drawer.setOnDrawerOpenListener(mockOpenListener);
- assertFalse(listener.hadOpenedDrawer());
+ verifyZeroInteractions(mockOpenListener);
drawer.open();
- assertTrue(listener.hadOpenedDrawer());
+ verify(mockOpenListener, times(1)).onDrawerOpened();
}
@UiThreadTest
public void testSetOnDrawerCloseListener() {
SlidingDrawer drawer = (SlidingDrawer) mActivity.findViewById(R.id.drawer);
- MockOnDrawerCloseListener listener = new MockOnDrawerCloseListener();
- drawer.setOnDrawerCloseListener(listener);
+ SlidingDrawer.OnDrawerCloseListener mockCloseListener =
+ mock(SlidingDrawer.OnDrawerCloseListener.class);
+ drawer.setOnDrawerCloseListener(mockCloseListener);
- assertFalse(listener.hadClosedDrawer());
+ verifyZeroInteractions(mockCloseListener);
drawer.open();
- assertFalse(listener.hadClosedDrawer());
+ verifyZeroInteractions(mockCloseListener);
drawer.close();
- assertTrue(listener.hadClosedDrawer());
+ verify(mockCloseListener, times(1)).onDrawerClosed();
}
public void testSetOnDrawerScrollListener() throws Throwable {
final SlidingDrawer drawer = (SlidingDrawer) mActivity.findViewById(R.id.drawer);
- MockOnDrawerScrollListener listener = new MockOnDrawerScrollListener();
- drawer.setOnDrawerScrollListener(listener);
- assertFalse(listener.hadStartedScroll());
- assertFalse(listener.hadEndedScroll());
- runTestOnUiThread(new Runnable() {
- public void run() {
- drawer.animateOpen();
- }
- });
- if ( !listener.hadStartedScroll() ) {
- synchronized (mLock) {
- mLock.wait(TEST_TIMEOUT);
- }
- }
- assertTrue(listener.hadStartedScroll());
+ final CountDownLatch countDownLatch = new CountDownLatch(2);
+ final SlidingDrawer.OnDrawerScrollListener mockScrollListener =
+ mock(SlidingDrawer.OnDrawerScrollListener.class);
+ doAnswer((InvocationOnMock invocation) -> {
+ countDownLatch.countDown();
+ return null;
+ }).when(mockScrollListener).onScrollStarted();
+ doAnswer((InvocationOnMock invocation) -> {
+ countDownLatch.countDown();
+ return null;
+ }).when(mockScrollListener).onScrollEnded();
+ drawer.setOnDrawerScrollListener(mockScrollListener);
- if ( !listener.hadEndedScroll() ) {
- synchronized (mLock) {
- mLock.wait(TEST_TIMEOUT);
- }
+ runTestOnUiThread(() -> drawer.animateOpen());
+
+ try {
+ countDownLatch.await(2 * TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException ie) {
+ // Do nothing as we're about to verify that both callbacks have been called
+ // in any case
}
- assertTrue(listener.hadStartedScroll());
- assertTrue(listener.hadEndedScroll());
+
+ InOrder inOrder = inOrder(mockScrollListener);
+ inOrder.verify(mockScrollListener).onScrollStarted();
+ inOrder.verify(mockScrollListener).onScrollEnded();
+ verifyNoMoreInteractions(mockScrollListener);
}
public void testOnLayout() {
@@ -329,56 +281,4 @@
public void testOnTouchEvent() {
// onTouchEvent() is implementation details, do NOT test
}
-
- private static final class MockOnDrawerOpenListener implements OnDrawerOpenListener {
- private boolean mHadOpenedDrawer = false;
-
- public void onDrawerOpened() {
- mHadOpenedDrawer = true;
- }
-
- public boolean hadOpenedDrawer() {
- return mHadOpenedDrawer;
- }
- }
-
- private static final class MockOnDrawerCloseListener implements OnDrawerCloseListener {
- private boolean mHadClosedDrawer = false;
-
- public void onDrawerClosed() {
- mHadClosedDrawer = true;
- }
-
- public boolean hadClosedDrawer() {
- return mHadClosedDrawer;
- }
- }
-
- private final class MockOnDrawerScrollListener implements OnDrawerScrollListener {
- private boolean mHadEndedScroll = false;
- private boolean mHadStartedScroll = false;
-
- public void onScrollEnded() {
- synchronized (mLock) {
- assertTrue(mHadStartedScroll);
- mHadEndedScroll = true;
- mLock.notify();
- }
- }
-
- public void onScrollStarted() {
- synchronized (mLock) {
- mHadStartedScroll = true;
- mLock.notify();
- }
- }
-
- public boolean hadEndedScroll() {
- return mHadEndedScroll;
- }
-
- public boolean hadStartedScroll() {
- return mHadStartedScroll;
- }
- }
}
diff --git a/tests/tests/widget/src/android/widget/cts/SpinnerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/SpinnerCtsActivity.java
new file mode 100644
index 0000000..16fb30e
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/SpinnerCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.Spinner;
+
+/**
+ * A minimal application for {@link Spinner} test.
+ */
+public class SpinnerCtsActivity extends Activity {
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.spinner_layout);
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/SpinnerTest.java b/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
index eea1e3e..62fe412 100644
--- a/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
@@ -16,101 +16,163 @@
package android.widget.cts;
-import android.widget.cts.R;
-
-
+import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
-import android.content.Context;
+import android.app.Instrumentation;
+import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.content.res.Resources.Theme;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
import android.view.ContextThemeWrapper;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
+
+import static org.mockito.Mockito.mock;
/**
* Test {@link Spinner}.
*/
-public class SpinnerTest extends ActivityInstrumentationTestCase2<RelativeLayoutCtsActivity> {
- private Context mTargetContext;
+@MediumTest
+public class SpinnerTest extends ActivityInstrumentationTestCase2<SpinnerCtsActivity> {
+ private Activity mActivity;
+ private Spinner mSpinnerDialogMode;
+ private Spinner mSpinnerDropdownMode;
public SpinnerTest() {
- super("android.widget.cts", RelativeLayoutCtsActivity.class);
+ super("android.widget.cts", SpinnerCtsActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
- mTargetContext = getInstrumentation().getTargetContext();
+
+ mActivity = getActivity();
+ mSpinnerDialogMode = (Spinner) mActivity.findViewById(R.id.spinner_dialog_mode);
+ mSpinnerDropdownMode = (Spinner) mActivity.findViewById(R.id.spinner_dropdown_mode);
}
- @UiThreadTest
public void testConstructor() {
- new Spinner(mTargetContext);
+ new Spinner(mActivity);
- new Spinner(mTargetContext, null);
+ new Spinner(mActivity, null);
- new Spinner(mTargetContext, null, android.R.attr.spinnerStyle);
+ new Spinner(mActivity, null, android.R.attr.spinnerStyle);
- new Spinner(mTargetContext, Spinner.MODE_DIALOG);
+ new Spinner(mActivity, Spinner.MODE_DIALOG);
- new Spinner(mTargetContext, null, android.R.attr.spinnerStyle,
+ new Spinner(mActivity, Spinner.MODE_DROPDOWN);
+
+ new Spinner(mActivity, null, android.R.attr.spinnerStyle, Spinner.MODE_DIALOG);
+
+ new Spinner(mActivity, null, android.R.attr.spinnerStyle, Spinner.MODE_DROPDOWN);
+
+ new Spinner(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Spinner,
Spinner.MODE_DIALOG);
- new Spinner(mTargetContext, null, android.R.attr.spinnerStyle, 0,
+ new Spinner(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Spinner,
+ Spinner.MODE_DROPDOWN);
+
+ new Spinner(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_Spinner,
Spinner.MODE_DIALOG);
- new Spinner(mTargetContext, null, android.R.attr.spinnerStyle, 0,
- Spinner.MODE_DIALOG, mTargetContext.getTheme());
+ new Spinner(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_Spinner,
+ Spinner.MODE_DROPDOWN);
- Spinner spinner = (Spinner) getActivity().findViewById(R.id.spinner1);
- assertEquals(mTargetContext.getString(R.string.text_view_hello), spinner.getPrompt());
+ new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Spinner,
+ Spinner.MODE_DIALOG);
+
+ new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Spinner,
+ Spinner.MODE_DROPDOWN);
+
+ new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Spinner_Underlined,
+ Spinner.MODE_DIALOG);
+
+ new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Spinner_Underlined,
+ Spinner.MODE_DROPDOWN);
+
+ new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Light_Spinner,
+ Spinner.MODE_DIALOG);
+
+ new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Light_Spinner,
+ Spinner.MODE_DROPDOWN);
+
+ new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Light_Spinner_Underlined,
+ Spinner.MODE_DIALOG);
+
+ new Spinner(mActivity, null, 0, android.R.style.Widget_Material_Light_Spinner_Underlined,
+ Spinner.MODE_DROPDOWN);
+
+ final Resources.Theme popupTheme = mActivity.getResources().newTheme();
+ popupTheme.applyStyle(android.R.style.Theme_Material, true);
+
+ new Spinner(mActivity, null, android.R.attr.spinnerStyle, 0, Spinner.MODE_DIALOG,
+ popupTheme);
+
+ new Spinner(mActivity, null, android.R.attr.spinnerStyle, 0, Spinner.MODE_DROPDOWN,
+ popupTheme);
}
- @UiThreadTest
- public void testGetBaseline() {
- Spinner spinner = new Spinner(mTargetContext);
-
+ private void verifyGetBaseline(Spinner spinner) {
assertEquals(-1, spinner.getBaseline());
- spinner = (Spinner) getActivity().findViewById(R.id.spinner1);
- ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mTargetContext,
- android.widget.cts.R.array.string, android.R.layout.simple_spinner_item);
+ ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+ R.array.string, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- spinner.setAdapter(adapter);
- assertTrue(spinner.getBaseline() > 0);
+ getInstrumentation().runOnMainSync(() -> {
+ spinner.setAdapter(adapter);
+ assertTrue(spinner.getBaseline() > 0);
+ });
}
- @UiThreadTest
- public void testSetOnItemClickListener() {
- Spinner spinner = new Spinner(mTargetContext);
+ public void testGetBaseline() {
+ verifyGetBaseline(mSpinnerDialogMode);
+ verifyGetBaseline(mSpinnerDropdownMode);
+ }
+ private void verifySetOnItemClickListener(Spinner spinner) {
try {
spinner.setOnItemClickListener(null);
fail("Should throw RuntimeException");
} catch (RuntimeException e) {
}
+
+ try {
+ spinner.setOnItemClickListener(mock(Spinner.OnItemClickListener.class));
+ fail("Should throw RuntimeException");
+ } catch (RuntimeException e) {
+ }
}
- @UiThreadTest
+ public void testSetOnItemClickListener() {
+ verifySetOnItemClickListener(mSpinnerDialogMode);
+ verifySetOnItemClickListener(mSpinnerDropdownMode);
+ }
+
+ private void verifyPerformClick(Spinner spinner) {
+ getInstrumentation().runOnMainSync(() -> assertTrue(spinner.performClick()));
+ }
+
public void testPerformClick() {
- final Spinner spinner = (Spinner) getActivity().findViewById(R.id.spinner1);
-
- assertTrue(spinner.performClick());
-
- // TODO: no description for the expected result for this method in its javadoc, issue?
- // Or do UI check?
+ verifyPerformClick(mSpinnerDialogMode);
+ verifyPerformClick(mSpinnerDropdownMode);
}
- @UiThreadTest
- public void testOnClick() {
- Spinner spinner = new Spinner(mTargetContext);
+ private void verifyOnClick(Spinner spinner) {
// normal value
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
AlertDialog alertDialog = builder.show();
assertTrue(alertDialog.isShowing());
+
spinner.onClick(alertDialog, 10);
assertEquals(10, spinner.getSelectedItemPosition());
assertFalse(alertDialog.isShowing());
@@ -125,32 +187,42 @@
Dialog dialog = new Dialog(getActivity());
dialog.show();
assertTrue(dialog.isShowing());
+
spinner.onClick(dialog, -10);
assertEquals(-10, spinner.getSelectedItemPosition());
assertFalse(dialog.isShowing());
}
@UiThreadTest
- public void testAccessPrompt() {
+ public void testOnClick() {
+ verifyOnClick(mSpinnerDialogMode);
+ verifyOnClick(mSpinnerDropdownMode);
+ }
+
+ private void verifyAccessPrompt(Spinner spinner) {
+ final String initialPrompt = mActivity.getString(R.string.text_view_hello);
+ assertEquals(initialPrompt, spinner.getPrompt());
+
+ final Instrumentation instrumentation = getInstrumentation();
final String promptText = "prompt text";
- Spinner spinner = new Spinner(mTargetContext);
-
- spinner.setPrompt(promptText);
+ instrumentation.runOnMainSync(() -> spinner.setPrompt(promptText));
assertEquals(promptText, spinner.getPrompt());
spinner.setPrompt(null);
assertNull(spinner.getPrompt());
-
- // TODO: find the dialog and get its title to assert whether setPrompt() takes effect?
}
- @UiThreadTest
- public void testSetPromptId() {
- Spinner spinner = new Spinner(mTargetContext);
+ public void testAccessPrompt() {
+ verifyAccessPrompt(mSpinnerDialogMode);
+ verifyAccessPrompt(mSpinnerDropdownMode);
+ }
- spinner.setPromptId(R.string.hello_world);
- assertEquals(mTargetContext.getString(R.string.hello_world), spinner.getPrompt());
+ private void verifySetPromptId(Spinner spinner) {
+ final Instrumentation instrumentation = getInstrumentation();
+
+ instrumentation.runOnMainSync(() -> spinner.setPromptId(R.string.hello_world));
+ assertEquals(mActivity.getString(R.string.hello_world), spinner.getPrompt());
try {
spinner.setPromptId(-1);
@@ -165,23 +237,209 @@
} catch (NotFoundException e) {
// issue 1695243, not clear what is supposed to happen if promptId is exceptional.
}
+ }
- // TODO: find the dialog and get its title to assert whether setPromptId() takes effect?
+ public void testSetPromptId() {
+ verifySetPromptId(mSpinnerDialogMode);
+ verifySetPromptId(mSpinnerDropdownMode);
}
@UiThreadTest
public void testGetPopupContext() {
- Theme theme = mTargetContext.getResources().newTheme();
- Spinner themeSpinner = new Spinner(mTargetContext, null,
+ Theme theme = mActivity.getResources().newTheme();
+ Spinner themeSpinner = new Spinner(mActivity, null,
android.R.attr.spinnerStyle, 0, Spinner.MODE_DIALOG, theme);
- assertNotSame(mTargetContext, themeSpinner.getPopupContext());
+ assertNotSame(mActivity, themeSpinner.getPopupContext());
assertSame(theme, themeSpinner.getPopupContext().getTheme());
ContextThemeWrapper context = (ContextThemeWrapper)themeSpinner.getPopupContext();
- assertSame(mTargetContext, context.getBaseContext());
+ assertSame(mActivity, context.getBaseContext());
}
- public void testOnLayout() {
- // onLayout() is implementation details, do NOT test
+ private void verifyGravity(Spinner spinner) {
+ final Instrumentation instrumentation = getInstrumentation();
+
+ // Note that here we're using a custom layout for the spinner's selected item
+ // that doesn't span the whole width of the parent. That way we're exercising the
+ // relevant path in spinner's layout pass that handles the currently set gravity
+ ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+ R.array.string, R.layout.simple_spinner_item_layout);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ instrumentation.runOnMainSync(() -> spinner.setAdapter(adapter));
+
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, spinner, () -> {
+ spinner.setSelection(1);
+ spinner.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
+ spinner.requestLayout();
+ });
+
+ instrumentation.runOnMainSync(() -> spinner.setGravity(Gravity.LEFT));
+ assertEquals(Gravity.LEFT, spinner.getGravity());
+
+ instrumentation.runOnMainSync(() -> spinner.setGravity(Gravity.CENTER_HORIZONTAL));
+ assertEquals(Gravity.CENTER_HORIZONTAL, spinner.getGravity());
+
+ instrumentation.runOnMainSync((() -> spinner.setGravity(Gravity.RIGHT)));
+ assertEquals(Gravity.RIGHT, spinner.getGravity());
+
+ instrumentation.runOnMainSync(() -> spinner.setGravity(Gravity.START));
+ assertEquals(Gravity.START, spinner.getGravity());
+
+ instrumentation.runOnMainSync(() -> spinner.setGravity(Gravity.END));
+ assertEquals(Gravity.END, spinner.getGravity());
+ }
+
+ public void testGravity() {
+ verifyGravity(mSpinnerDialogMode);
+ verifyGravity(mSpinnerDropdownMode);
+ }
+
+ public void testDropDownMetricsDropdownMode() {
+ final Instrumentation instrumentation = getInstrumentation();
+
+ ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+ R.array.string, android.R.layout.simple_spinner_item);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ instrumentation.runOnMainSync(() -> mSpinnerDropdownMode.setAdapter(adapter));
+
+ final Resources res = mActivity.getResources();
+ final int dropDownWidth = res.getDimensionPixelSize(R.dimen.spinner_dropdown_width);
+ final int dropDownOffsetHorizontal =
+ res.getDimensionPixelSize(R.dimen.spinner_dropdown_offset_h);
+ final int dropDownOffsetVertical =
+ res.getDimensionPixelSize(R.dimen.spinner_dropdown_offset_v);
+
+ instrumentation.runOnMainSync(() -> {
+ mSpinnerDropdownMode.setDropDownWidth(dropDownWidth);
+ mSpinnerDropdownMode.setDropDownHorizontalOffset(dropDownOffsetHorizontal);
+ mSpinnerDropdownMode.setDropDownVerticalOffset(dropDownOffsetVertical);
+ });
+
+ // Use instrumentation to emulate a tap on the spinner to bring down its popup
+ ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDropdownMode);
+ // Verify that we're showing the popup
+ assertTrue(mSpinnerDropdownMode.isPopupShowing());
+
+ // And test its attributes
+ assertEquals(dropDownWidth, mSpinnerDropdownMode.getDropDownWidth());
+ // TODO: restore when b/28089349 is addressed
+ // assertEquals(dropDownOffsetHorizontal,
+ // mSpinnerDropdownMode.getDropDownHorizontalOffset());
+ assertEquals(dropDownOffsetVertical, mSpinnerDropdownMode.getDropDownVerticalOffset());
+ }
+
+ public void testDropDownMetricsDialogMode() {
+ final Instrumentation instrumentation = getInstrumentation();
+
+ ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+ R.array.string, android.R.layout.simple_spinner_item);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ instrumentation.runOnMainSync(() -> mSpinnerDialogMode.setAdapter(adapter));
+
+ final Resources res = mActivity.getResources();
+ final int dropDownWidth = res.getDimensionPixelSize(R.dimen.spinner_dropdown_width);
+ final int dropDownOffsetHorizontal =
+ res.getDimensionPixelSize(R.dimen.spinner_dropdown_offset_h);
+ final int dropDownOffsetVertical =
+ res.getDimensionPixelSize(R.dimen.spinner_dropdown_offset_v);
+
+ instrumentation.runOnMainSync(() -> {
+ // These are all expected to be no-ops
+ mSpinnerDialogMode.setDropDownWidth(dropDownWidth);
+ mSpinnerDialogMode.setDropDownHorizontalOffset(dropDownOffsetHorizontal);
+ mSpinnerDialogMode.setDropDownVerticalOffset(dropDownOffsetVertical);
+ });
+
+ // Use instrumentation to emulate a tap on the spinner to bring down its popup
+ ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDialogMode);
+ // Verify that we're showing the popup
+ assertTrue(mSpinnerDialogMode.isPopupShowing());
+
+ // And test its attributes. Note that we are not testing the result of getDropDownWidth
+ // for this mode
+ assertEquals(0, mSpinnerDialogMode.getDropDownHorizontalOffset());
+ assertEquals(0, mSpinnerDialogMode.getDropDownVerticalOffset());
+ }
+
+ public void testDropDownBackgroundDropdownMode() {
+ final Instrumentation instrumentation = getInstrumentation();
+
+ ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+ R.array.string, android.R.layout.simple_spinner_item);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ instrumentation.runOnMainSync(() -> mSpinnerDropdownMode.setAdapter(adapter));
+
+ // Set blue background on the popup
+ instrumentation.runOnMainSync(() ->
+ mSpinnerDropdownMode.setPopupBackgroundResource(R.drawable.blue_fill));
+
+ // Use instrumentation to emulate a tap on the spinner to bring down its popup
+ ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDropdownMode);
+ // Verify that we're showing the popup
+ assertTrue(mSpinnerDropdownMode.isPopupShowing());
+ // And test its fill
+ Drawable dropDownBackground = mSpinnerDropdownMode.getPopupBackground();
+ TestUtils.assertAllPixelsOfColor("Drop down should be blue", dropDownBackground,
+ dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(),
+ false, Color.BLUE, 1, true);
+
+ // Dismiss the popup with the emulated back key
+ instrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+ instrumentation.waitForIdleSync();
+ // Verify that we're not showing the popup
+ assertFalse(mSpinnerDropdownMode.isPopupShowing());
+
+ // Set yellow background on the popup
+ instrumentation.runOnMainSync(() ->
+ mSpinnerDropdownMode.setPopupBackgroundDrawable(
+ mActivity.getDrawable(R.drawable.yellow_fill)));
+
+ // Use instrumentation to emulate a tap on the spinner to bring down its popup
+ ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDropdownMode);
+ // Verify that we're showing the popup
+ assertTrue(mSpinnerDropdownMode.isPopupShowing());
+ // And test its fill
+ dropDownBackground = mSpinnerDropdownMode.getPopupBackground();
+ TestUtils.assertAllPixelsOfColor("Drop down should be yellow", dropDownBackground,
+ dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(),
+ false, Color.YELLOW, 1, true);
+ }
+
+ public void testDropDownBackgroundDialogMode() {
+ final Instrumentation instrumentation = getInstrumentation();
+
+ ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mActivity,
+ R.array.string, android.R.layout.simple_spinner_item);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ instrumentation.runOnMainSync(() -> mSpinnerDialogMode.setAdapter(adapter));
+
+ // Set blue background on the popup
+ instrumentation.runOnMainSync(() ->
+ mSpinnerDialogMode.setPopupBackgroundResource(R.drawable.blue_fill));
+
+ // Use instrumentation to emulate a tap on the spinner to bring down its popup
+ ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDialogMode);
+ // Verify that we're showing the popup
+ assertTrue(mSpinnerDialogMode.isPopupShowing());
+ // And test that getPopupBackground returns null
+ assertNull(mSpinnerDialogMode.getPopupBackground());
+
+ // Dismiss the popup with the emulated back key
+ instrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+ instrumentation.waitForIdleSync();
+ // Verify that we're not showing the popup
+ assertFalse(mSpinnerDialogMode.isPopupShowing());
+
+ // Set yellow background on the popup
+ instrumentation.runOnMainSync(() ->
+ mSpinnerDialogMode.setPopupBackgroundDrawable(
+ mActivity.getDrawable(R.drawable.yellow_fill)));
+
+ // Use instrumentation to emulate a tap on the spinner to bring down its popup
+ ViewTestUtils.emulateTapOnViewCenter(instrumentation, mSpinnerDialogMode);
+ // Verify that we're showing the popup
+ assertTrue(mSpinnerDialogMode.isPopupShowing());
+ // And test that getPopupBackground returns null
+ assertNull(mSpinnerDialogMode.getPopupBackground());
}
}
diff --git a/tests/tests/widget/src/android/widget/cts/SwitchTest.java b/tests/tests/widget/src/android/widget/cts/SwitchTest.java
index 216b17b..fb449ed 100644
--- a/tests/tests/widget/src/android/widget/cts/SwitchTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SwitchTest.java
@@ -17,22 +17,28 @@
package android.widget.cts;
import android.app.Activity;
+import android.app.Instrumentation;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.PorterDuff.Mode;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
import android.test.ActivityInstrumentationTestCase;
+import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
import android.test.suitebuilder.annotation.SmallTest;
+import android.view.ContextThemeWrapper;
+import android.view.ViewGroup;
import android.widget.Switch;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
/**
* Test {@link Switch}.
*/
@SmallTest
-public class SwitchTest extends ActivityInstrumentationTestCase<SwitchCtsActivity> {
+public class SwitchTest extends ActivityInstrumentationTestCase2<SwitchCtsActivity> {
private Activity mActivity;
private Switch mSwitch;
@@ -44,7 +50,10 @@
protected void setUp() throws Exception {
super.setUp();
mActivity = getActivity();
- mSwitch = (Switch) mActivity.findViewById(R.id.switch_view);
+ }
+
+ private Switch findSwitchById(int id) {
+ return (Switch) mActivity.findViewById(id);
}
@UiThreadTest
@@ -55,11 +64,16 @@
new Switch(mActivity, null, android.R.attr.switchStyle);
+ new Switch(mActivity, null, 0, android.R.style.Widget_Material_CompoundButton_Switch);
+
new Switch(mActivity, null, 0, android.R.style.Widget_Material_Light_CompoundButton_Switch);
}
@UiThreadTest
public void testAccessThumbTint() {
+ mSwitch = findSwitchById(R.id.switch1);
+
+ // These are the default set in layout XML
assertEquals(Color.WHITE, mSwitch.getThumbTintList().getDefaultColor());
assertEquals(Mode.SRC_OVER, mSwitch.getThumbTintMode());
@@ -73,6 +87,9 @@
@UiThreadTest
public void testAccessTrackTint() {
+ mSwitch = findSwitchById(R.id.switch1);
+
+ // These are the default set in layout XML
assertEquals(Color.BLACK, mSwitch.getTrackTintList().getDefaultColor());
assertEquals(Mode.SRC_ATOP, mSwitch.getTrackTintMode());
@@ -83,4 +100,175 @@
assertSame(colors, mSwitch.getTrackTintList());
assertEquals(Mode.XOR, mSwitch.getTrackTintMode());
}
+
+ public void testAccessThumbDrawable() {
+ mSwitch = findSwitchById(R.id.switch2);
+ final Instrumentation instrumentation = getInstrumentation();
+
+ // This is the default set in layout XML
+ Drawable thumbDrawable = mSwitch.getThumbDrawable();
+ TestUtils.assertAllPixelsOfColor("Thumb drawable should be blue", thumbDrawable,
+ thumbDrawable.getIntrinsicWidth(), thumbDrawable.getIntrinsicHeight(), false,
+ Color.BLUE, 1, true);
+
+ // Change thumb drawable to red
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setThumbDrawable(mActivity.getDrawable(R.drawable.icon_red)));
+ thumbDrawable = mSwitch.getThumbDrawable();
+ TestUtils.assertAllPixelsOfColor("Thumb drawable should be red", thumbDrawable,
+ thumbDrawable.getIntrinsicWidth(), thumbDrawable.getIntrinsicHeight(), false,
+ Color.RED, 1, true);
+
+ // Change thumb drawable to green
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setThumbResource(R.drawable.icon_green));
+ thumbDrawable = mSwitch.getThumbDrawable();
+ TestUtils.assertAllPixelsOfColor("Thumb drawable should be green", thumbDrawable,
+ thumbDrawable.getIntrinsicWidth(), thumbDrawable.getIntrinsicHeight(), false,
+ Color.GREEN, 1, true);
+
+ // Now tint the latest (green) thumb drawable with 50% blue SRC_OVER
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch, () -> {
+ mSwitch.setThumbTintList(ColorStateList.valueOf(0x800000FF));
+ mSwitch.setThumbTintMode(Mode.SRC_OVER);
+ });
+ thumbDrawable = mSwitch.getThumbDrawable();
+ TestUtils.assertAllPixelsOfColor("Thumb drawable should be green / blue", thumbDrawable,
+ thumbDrawable.getIntrinsicWidth(), thumbDrawable.getIntrinsicHeight(), false,
+ TestUtils.compositeColors(0x800000FF, Color.GREEN), 1, true);
+ }
+
+ public void testAccessTrackDrawable() {
+ mSwitch = findSwitchById(R.id.switch2);
+ final Instrumentation instrumentation = getInstrumentation();
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setTrackTintMode(Mode.DST));
+
+ // This is the default set in layout XML
+ Drawable trackDrawable = mSwitch.getTrackDrawable();
+ Rect trackDrawableBounds = trackDrawable.getBounds();
+ TestUtils.assertAllPixelsOfColor("Track drawable should be 50% red", trackDrawable,
+ trackDrawableBounds.width(), trackDrawableBounds.height(), false,
+ 0x80FF0000, 1, true);
+
+ // Change track drawable to blue
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setTrackDrawable(mActivity.getDrawable(R.drawable.blue_fill)));
+ trackDrawable = mSwitch.getTrackDrawable();
+ trackDrawableBounds = trackDrawable.getBounds();
+ TestUtils.assertAllPixelsOfColor("Track drawable should be blue", trackDrawable,
+ trackDrawableBounds.width(), trackDrawableBounds.height(), false,
+ Color.BLUE, 1, true);
+
+ // Change track drawable to green
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setTrackResource(R.drawable.green_fill));
+ trackDrawable = mSwitch.getTrackDrawable();
+ trackDrawableBounds = trackDrawable.getBounds();
+ TestUtils.assertAllPixelsOfColor("Track drawable should be green", trackDrawable,
+ trackDrawableBounds.width(), trackDrawableBounds.height(), false,
+ Color.GREEN, 1, true);
+
+ // Now tint the latest (green) track drawable with 50% blue SRC_OVER
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch, () -> {
+ mSwitch.setTrackTintList(ColorStateList.valueOf(0x800000FF));
+ mSwitch.setTrackTintMode(Mode.SRC_OVER);
+ });
+ trackDrawable = mSwitch.getTrackDrawable();
+ trackDrawableBounds = trackDrawable.getBounds();
+ TestUtils.assertAllPixelsOfColor("Track drawable should be green / blue", trackDrawable,
+ trackDrawableBounds.width(), trackDrawableBounds.height(), false,
+ TestUtils.compositeColors(0x800000FF, Color.GREEN), 1, true);
+ }
+
+ public void testAccessText() {
+ final Instrumentation instrumentation = getInstrumentation();
+
+ // Run text-related tests on a Holo-themed switch, since under Material themes we
+ // are not showing texts by default.
+ mSwitch = new Switch(new ContextThemeWrapper(mActivity, android.R.style.Theme_Holo_Light));
+ instrumentation.runOnMainSync(
+ () -> ((ViewGroup) mActivity.findViewById(R.id.container)).addView(mSwitch));
+
+ // Set "on" text and verify it
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setTextOn("Text on"));
+ assertEquals("Text on", mSwitch.getTextOn());
+
+ // Set "off" text and verify it
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setTextOff("Text off"));
+ assertEquals("Text off", mSwitch.getTextOff());
+
+ // Turn text display on
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setShowText(true));
+ assertTrue(mSwitch.getShowText());
+
+ // Use custom text appearance. Since we don't have APIs to query this facet of Switch,
+ // just test that it's not crashing.
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setSwitchTextAppearance(mActivity, R.style.TextAppearance_WithColor));
+
+ // Use custom typeface. Since we don't have APIs to query this facet of Switch,
+ // just test that it's not crashing.
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setSwitchTypeface(Typeface.MONOSPACE));
+
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setSwitchTypeface(Typeface.SERIF, Typeface.ITALIC));
+
+ // Set and verify padding between the thumb and the text
+ final int thumbTextPadding = mActivity.getResources().getDimensionPixelSize(
+ R.dimen.switch_thumb_text_padding);
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setThumbTextPadding(thumbTextPadding));
+ assertEquals(thumbTextPadding, mSwitch.getThumbTextPadding());
+
+ // Set and verify padding between the switch and the text
+ final int switchPadding = mActivity.getResources().getDimensionPixelSize(
+ R.dimen.switch_padding);
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setSwitchPadding(switchPadding));
+ assertEquals(switchPadding, mSwitch.getSwitchPadding());
+
+ // Turn text display off
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setShowText(false));
+ assertFalse(mSwitch.getShowText());
+ }
+
+ public void testAccessMinWidth() {
+ mSwitch = findSwitchById(R.id.switch3);
+ final Instrumentation instrumentation = getInstrumentation();
+
+ // Set custom min width on the switch and verify that it's at least that wide
+ final int switchMinWidth = mActivity.getResources().getDimensionPixelSize(
+ R.dimen.switch_min_width);
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setSwitchMinWidth(switchMinWidth));
+ assertEquals(switchMinWidth, mSwitch.getSwitchMinWidth());
+ assertTrue(mSwitch.getWidth() >= switchMinWidth);
+
+ // And set another (larger) min width
+ final int switchMinWidth2 = mActivity.getResources().getDimensionPixelSize(
+ R.dimen.switch_min_width2);
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setSwitchMinWidth(switchMinWidth2));
+ assertEquals(switchMinWidth2, mSwitch.getSwitchMinWidth());
+ assertTrue(mSwitch.getWidth() >= switchMinWidth2);
+ }
+
+ public void testAccessSplitTrack() {
+ mSwitch = findSwitchById(R.id.switch3);
+ final Instrumentation instrumentation = getInstrumentation();
+
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setSplitTrack(true));
+ assertTrue(mSwitch.getSplitTrack());
+
+ ViewTestUtils.runOnMainAndDrawSync(instrumentation, mSwitch,
+ () -> mSwitch.setSplitTrack(false));
+ assertFalse(mSwitch.getSplitTrack());
+ }
}
diff --git a/tests/tests/widget/src/android/widget/cts/TableLayoutTest.java b/tests/tests/widget/src/android/widget/cts/TableLayoutTest.java
index ccf22d9..d35e5cb 100644
--- a/tests/tests/widget/src/android/widget/cts/TableLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TableLayoutTest.java
@@ -16,8 +16,6 @@
package android.widget.cts;
-import android.widget.cts.R;
-
import android.content.Context;
import android.content.res.XmlResourceParser;
import android.test.ActivityInstrumentationTestCase2;
@@ -25,9 +23,8 @@
import android.util.AttributeSet;
import android.util.Xml;
import android.view.View;
-import android.view.ViewGroup;
import android.view.View.MeasureSpec;
-import android.view.ViewGroup.OnHierarchyChangeListener;
+import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
@@ -35,6 +32,8 @@
import android.widget.TableRow;
import android.widget.TextView;
+import static org.mockito.Mockito.*;
+
/**
* Test {@link TableLayout}.
*/
@@ -72,21 +71,21 @@
public void testSetOnHierarchyChangeListener() {
TableLayout tableLayout = new TableLayout(mContext);
- MockOnHierarchyChangeListener listener = new MockOnHierarchyChangeListener();
- tableLayout.setOnHierarchyChangeListener(listener);
+ ViewGroup.OnHierarchyChangeListener mockHierarchyChangeListener =
+ mock(ViewGroup.OnHierarchyChangeListener.class);
+ tableLayout.setOnHierarchyChangeListener(mockHierarchyChangeListener);
- tableLayout.addView(new TextView(mContext));
- assertTrue(listener.hasCalledOnChildViewAdded());
+ View toAdd = new TextView(mContext);
+ tableLayout.addView(toAdd);
+ verify(mockHierarchyChangeListener, times(1)).onChildViewAdded(tableLayout, toAdd);
tableLayout.removeViewAt(0);
- assertTrue(listener.hasCalledOnChildViewRemoved());
-
- listener.reset();
+ verify(mockHierarchyChangeListener, times(1)).onChildViewRemoved(tableLayout, toAdd);
+ verifyNoMoreInteractions(mockHierarchyChangeListener);
tableLayout.setOnHierarchyChangeListener(null);
tableLayout.addView(new TextView(mContext));
- assertFalse(listener.hasCalledOnChildViewAdded());
tableLayout.removeViewAt(0);
- assertFalse(listener.hasCalledOnChildViewRemoved());
+ verifyNoMoreInteractions(mockHierarchyChangeListener);
}
public void testRequestLayout() {
@@ -456,7 +455,8 @@
assertNull(child1.getLayoutParams());
tableLayout.addView(child1, new ViewGroup.LayoutParams(100, 200));
assertSame(child1, tableLayout.getChildAt(0));
- assertEquals(100, tableLayout.getChildAt(0).getLayoutParams().width);
+ assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+ tableLayout.getChildAt(0).getLayoutParams().width);
assertEquals(200, tableLayout.getChildAt(0).getLayoutParams().height);
assertTrue(tableLayout.getChildAt(0).isLayoutRequested());
@@ -467,9 +467,11 @@
tableLayout.addView(child2, new TableRow.LayoutParams(200, 300, 1));
assertSame(child1, tableLayout.getChildAt(0));
assertSame(child2, tableLayout.getChildAt(1));
- assertEquals(100, tableLayout.getChildAt(0).getLayoutParams().width);
+ assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+ tableLayout.getChildAt(0).getLayoutParams().width);
assertEquals(200, tableLayout.getChildAt(0).getLayoutParams().height);
- assertEquals(200, tableLayout.getChildAt(1).getLayoutParams().width);
+ assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+ tableLayout.getChildAt(1).getLayoutParams().width);
assertEquals(300, tableLayout.getChildAt(1).getLayoutParams().height);
assertTrue(tableLayout.getChildAt(0).isLayoutRequested());
assertTrue(tableLayout.getChildAt(1).isLayoutRequested());
@@ -494,7 +496,8 @@
assertNull(child1.getLayoutParams());
tableLayout.addView(child1, 0, new ViewGroup.LayoutParams(100, 200));
assertSame(child1, tableLayout.getChildAt(0));
- assertEquals(100, tableLayout.getChildAt(0).getLayoutParams().width);
+ assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+ tableLayout.getChildAt(0).getLayoutParams().width);
assertEquals(200, tableLayout.getChildAt(0).getLayoutParams().height);
assertTrue(tableLayout.getChildAt(0).isLayoutRequested());
@@ -505,9 +508,11 @@
tableLayout.addView(child2, 0, new TableRow.LayoutParams(200, 300, 1));
assertSame(child2, tableLayout.getChildAt(0));
assertSame(child1, tableLayout.getChildAt(1));
- assertEquals(200, tableLayout.getChildAt(0).getLayoutParams().width);
+ assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+ tableLayout.getChildAt(0).getLayoutParams().width);
assertEquals(300, tableLayout.getChildAt(0).getLayoutParams().height);
- assertEquals(100, tableLayout.getChildAt(1).getLayoutParams().width);
+ assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+ tableLayout.getChildAt(1).getLayoutParams().width);
assertEquals(200, tableLayout.getChildAt(1).getLayoutParams().height);
assertTrue(tableLayout.getChildAt(0).isLayoutRequested());
assertTrue(tableLayout.getChildAt(1).isLayoutRequested());
@@ -520,11 +525,14 @@
assertSame(child2, tableLayout.getChildAt(0));
assertSame(child1, tableLayout.getChildAt(1));
assertSame(child3, tableLayout.getChildAt(2));
- assertEquals(200, tableLayout.getChildAt(0).getLayoutParams().width);
+ assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+ tableLayout.getChildAt(0).getLayoutParams().width);
assertEquals(300, tableLayout.getChildAt(0).getLayoutParams().height);
- assertEquals(100, tableLayout.getChildAt(1).getLayoutParams().width);
+ assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+ tableLayout.getChildAt(1).getLayoutParams().width);
assertEquals(200, tableLayout.getChildAt(1).getLayoutParams().height);
- assertEquals(300, tableLayout.getChildAt(2).getLayoutParams().width);
+ assertEquals(ViewGroup.LayoutParams.MATCH_PARENT,
+ tableLayout.getChildAt(2).getLayoutParams().width);
assertEquals(400, tableLayout.getChildAt(2).getLayoutParams().height);
assertTrue(tableLayout.getChildAt(0).isLayoutRequested());
assertTrue(tableLayout.getChildAt(1).isLayoutRequested());
@@ -588,7 +596,7 @@
LinearLayout.LayoutParams layoutParams = mockTableLayout.generateLayoutParams(
new ViewGroup.LayoutParams(200, 300));
assertNotNull(layoutParams);
- assertEquals(200, layoutParams.width);
+ assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, layoutParams.width);
assertEquals(300, layoutParams.height);
assertTrue(layoutParams instanceof TableLayout.LayoutParams);
@@ -611,50 +619,6 @@
mockTableLayout.onMeasure(MeasureSpec.EXACTLY, MeasureSpec.EXACTLY);
}
- private int dropNegative(int number) {
- return (number > 0 ? number : 0);
- }
-
- private class MockOnHierarchyChangeListener implements OnHierarchyChangeListener {
- private boolean mCalledOnChildViewAdded = false;
- private boolean mCalledOnChildViewRemoved = false;
-
- /*
- * (non-Javadoc)
- *
- * @see
- * android.view.ViewGroup.OnHierarchyChangeListener#onChildViewAdded
- * (View, View)
- */
- public void onChildViewAdded(View parent, View child) {
- mCalledOnChildViewAdded = true;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * android.view.ViewGroup.OnHierarchyChangeListener#onChildViewRemoved
- * (View, View)
- */
- public void onChildViewRemoved(View parent, View child) {
- mCalledOnChildViewRemoved = true;
- }
-
- public boolean hasCalledOnChildViewAdded() {
- return mCalledOnChildViewAdded;
- }
-
- public boolean hasCalledOnChildViewRemoved() {
- return mCalledOnChildViewRemoved;
- }
-
- public void reset() {
- mCalledOnChildViewAdded = false;
- mCalledOnChildViewRemoved = false;
- }
- }
-
/*
* Mock class for TableLayout to test protected methods
*/
diff --git a/tests/tests/widget/src/android/widget/cts/TableLayout_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/TableLayout_LayoutParamsTest.java
index fbd9f97..077c134c 100644
--- a/tests/tests/widget/src/android/widget/cts/TableLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TableLayout_LayoutParamsTest.java
@@ -16,6 +16,7 @@
package android.widget.cts;
+import android.view.ViewGroup;
import android.widget.cts.R;
import org.xmlpull.v1.XmlPullParser;
@@ -42,28 +43,47 @@
}
public void testConstructor() {
- new TableLayout.LayoutParams(mTargetContext, null);
+ // We expect width to be MATCH and height to be WRAP as documented in TableLayout
+ TableLayout.LayoutParams layoutParams = new TableLayout.LayoutParams();
+ assertEquals(TableLayout.LayoutParams.MATCH_PARENT, layoutParams.width);
+ assertEquals(TableLayout.LayoutParams.WRAP_CONTENT, layoutParams.height);
- TableLayout.LayoutParams layoutParams = new TableLayout.LayoutParams(200, 300);
+ // We expect width to be MATCH and height to be WRAP as documented in TableLayout
+ layoutParams = new TableLayout.LayoutParams(mTargetContext, null);
+ assertEquals(TableLayout.LayoutParams.MATCH_PARENT, layoutParams.width);
+ assertEquals(TableLayout.LayoutParams.WRAP_CONTENT, layoutParams.height);
+
+ // We expect width to be MATCH, ignoring what is passed in the constructor
+ layoutParams = new TableLayout.LayoutParams(200, 300);
assertEquals(TableLayout.LayoutParams.MATCH_PARENT, layoutParams.width);
assertEquals(300, layoutParams.height);
- TableLayout.LayoutParams oldParams = layoutParams;
- layoutParams = new TableLayout.LayoutParams(200, 300, 1.2f);
+ // We expect width to be MATCH, ignoring what is passed in the constructor
+ layoutParams = new TableLayout.LayoutParams(250, 350, 1.2f);
assertEquals(TableLayout.LayoutParams.MATCH_PARENT, layoutParams.width);
- assertEquals(300, layoutParams.height);
+ assertEquals(350, layoutParams.height);
assertEquals(1.2f, layoutParams.weight);
- TableLayout.LayoutParams oldMarginParams = layoutParams;
- new TableLayout.LayoutParams();
-
- layoutParams = new TableLayout.LayoutParams(oldParams);
+ // We expect width to be MATCH, ignoring what is set on the passed object
+ layoutParams = new TableLayout.LayoutParams(new ViewGroup.LayoutParams(300, 360));
assertEquals(TableLayout.LayoutParams.MATCH_PARENT, layoutParams.width);
- assertEquals(300, layoutParams.height);
+ assertEquals(360, layoutParams.height);
- layoutParams = new TableLayout.LayoutParams(oldMarginParams);
+ // We expect width to be MATCH, ignoring what is set on the passed object
+ layoutParams = new TableLayout.LayoutParams(new ViewGroup.MarginLayoutParams(320, 420));
assertEquals(TableLayout.LayoutParams.MATCH_PARENT, layoutParams.width);
- assertEquals(300, layoutParams.height);
+ assertEquals(420, layoutParams.height);
+
+ // We expect width to be MATCH as that is copied from the passed object
+ layoutParams = new TableLayout.LayoutParams(new TableLayout.LayoutParams(500, 400));
+ assertEquals(TableLayout.LayoutParams.MATCH_PARENT, layoutParams.width);
+ assertEquals(400, layoutParams.height);
+
+ // We expect width to be MATCH as that is copied from the passed object
+ layoutParams = new TableLayout.LayoutParams(new TableLayout.LayoutParams(550, 650, 1.4f));
+ assertEquals(TableLayout.LayoutParams.MATCH_PARENT, layoutParams.width);
+ assertEquals(650, layoutParams.height);
+ assertEquals(1.4f, layoutParams.weight);
}
public void testSetBaseAttributes() {
diff --git a/tests/tests/widget/src/android/widget/cts/TableRowTest.java b/tests/tests/widget/src/android/widget/cts/TableRowTest.java
index 2e917f8..070769f 100644
--- a/tests/tests/widget/src/android/widget/cts/TableRowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TableRowTest.java
@@ -24,17 +24,15 @@
import android.util.AttributeSet;
import android.util.Xml;
import android.view.View;
-import android.view.ViewGroup;
import android.view.View.MeasureSpec;
-import android.view.ViewGroup.OnHierarchyChangeListener;
+import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
-import android.widget.cts.R;
-
+import static org.mockito.Mockito.*;
/**
* Test {@link TableRow}.
@@ -63,21 +61,21 @@
public void testSetOnHierarchyChangeListener() {
TableRow tableRow = new TableRow(mContext);
- MockOnHierarchyChangeListener listener = new MockOnHierarchyChangeListener();
- tableRow.setOnHierarchyChangeListener(listener);
+ ViewGroup.OnHierarchyChangeListener mockHierarchyChangeListener =
+ mock(ViewGroup.OnHierarchyChangeListener.class);
+ tableRow.setOnHierarchyChangeListener(mockHierarchyChangeListener);
- tableRow.addView(new TextView(mContext));
- assertTrue(listener.hasCalledOnChildViewAdded());
+ View toAdd = new TextView(mContext);
+ tableRow.addView(toAdd);
+ verify(mockHierarchyChangeListener, times(1)).onChildViewAdded(tableRow, toAdd);
tableRow.removeViewAt(0);
- assertTrue(listener.hasCalledOnChildViewRemoved());
-
- listener.reset();
+ verify(mockHierarchyChangeListener, times(1)).onChildViewRemoved(tableRow, toAdd);
+ verifyNoMoreInteractions(mockHierarchyChangeListener);
tableRow.setOnHierarchyChangeListener(null);
tableRow.addView(new TextView(mContext));
- assertFalse(listener.hasCalledOnChildViewAdded());
tableRow.removeViewAt(0);
- assertFalse(listener.hasCalledOnChildViewRemoved());
+ verifyNoMoreInteractions(mockHierarchyChangeListener);
}
@UiThreadTest
@@ -189,46 +187,6 @@
mockTableRow.onMeasure(MeasureSpec.EXACTLY, MeasureSpec.EXACTLY);
}
- private class MockOnHierarchyChangeListener implements OnHierarchyChangeListener {
- private boolean mCalledOnChildViewAdded = false;
- private boolean mCalledOnChildViewRemoved = false;
-
- /*
- * (non-Javadoc)
- *
- * @see
- * android.view.ViewGroup.OnHierarchyChangeListener#onChildViewAdded
- * (View, View)
- */
- public void onChildViewAdded(View parent, View child) {
- mCalledOnChildViewAdded = true;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * android.view.ViewGroup.OnHierarchyChangeListener#onChildViewRemoved
- * (View, View)
- */
- public void onChildViewRemoved(View parent, View child) {
- mCalledOnChildViewRemoved = true;
- }
-
- public boolean hasCalledOnChildViewAdded() {
- return mCalledOnChildViewAdded;
- }
-
- public boolean hasCalledOnChildViewRemoved() {
- return mCalledOnChildViewRemoved;
- }
-
- public void reset() {
- mCalledOnChildViewAdded = false;
- mCalledOnChildViewRemoved = false;
- }
- }
-
/*
* Mock class for TableRow to test protected methods
*/
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/TextViewCtsActivity.java
index 31fc486..0580150 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewCtsActivity.java
@@ -16,17 +16,16 @@
package android.widget.cts;
-import android.widget.cts.R;
-
import android.app.Activity;
import android.os.Bundle;
+import android.widget.TextView;
/**
- * A minimal application for TextView test.
+ * A minimal application for {@link TextView} test.
*/
public class TextViewCtsActivity extends Activity {
/**
- * Called with the activity is first created.
+ * Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewFadingEdgeTest.java b/tests/tests/widget/src/android/widget/cts/TextViewFadingEdgeTest.java
index e627c2b..8334604 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewFadingEdgeTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewFadingEdgeTest.java
@@ -120,12 +120,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- new PollingCheck() {
- @Override
- protected boolean check() {
- return getActivity().hasWindowFocus();
- }
- }.run();
+ PollingCheck.waitFor(() -> getActivity().hasWindowFocus());
}
public void testFadingEdge() {
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index 9f611ad..ee8974f 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -16,12 +16,16 @@
package android.widget.cts;
+import android.annotation.IdRes;
+import android.annotation.NonNull;
import android.app.Activity;
import android.app.Instrumentation;
import android.app.Instrumentation.ActivityMonitor;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
+import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.cts.util.KeyEventUtil;
import android.cts.util.PollingCheck;
@@ -39,8 +43,11 @@
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
+import android.os.Handler;
import android.os.LocaleList;
+import android.os.Looper;
import android.os.Parcelable;
+import android.os.ResultReceiver;
import android.test.ActivityInstrumentationTestCase2;
import android.test.TouchUtils;
import android.test.UiThreadTest;
@@ -85,10 +92,7 @@
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
-import android.view.MenuItem;
import android.view.View;
-import android.view.View.OnCreateContextMenuListener;
-import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.inputmethod.BaseInputConnection;
@@ -96,19 +100,27 @@
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
+import android.widget.ScrollView;
import android.widget.Scroller;
import android.widget.TextView;
import android.widget.TextView.BufferType;
-import android.widget.TextView.OnEditorActionListener;
+import android.widget.cts.util.TestUtils;
+import android.widget.cts.util.ViewTestUtils;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.Locale;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
+
/**
* Test {@link TextView}.
*/
@@ -125,6 +137,7 @@
private static final long TIMEOUT = 5000;
private CharSequence mTransformedText;
private KeyEventUtil mKeyEventUtil;
+ private Handler mHandler = new Handler(Looper.getMainLooper());
public TextViewTest() {
super("android.widget.cts", TextViewCtsActivity.class);
@@ -134,12 +147,7 @@
protected void setUp() throws Exception {
super.setUp();
mActivity = getActivity();
- new PollingCheck() {
- @Override
- protected boolean check() {
- return mActivity.hasWindowFocus();
- }
- }.run();
+ PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
mInstrumentation = getInstrumentation();
mKeyEventUtil = new KeyEventUtil(mInstrumentation);
}
@@ -164,7 +172,15 @@
new TextView(mActivity, null);
- new TextView(mActivity, null, 0);
+ new TextView(mActivity, null, android.R.attr.textViewStyle);
+
+ new TextView(mActivity, null, 0, android.R.style.Widget_DeviceDefault_TextView);
+
+ new TextView(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Light_TextView);
+
+ new TextView(mActivity, null, 0, android.R.style.Widget_Material_TextView);
+
+ new TextView(mActivity, null, 0, android.R.style.Widget_Material_Light_TextView);
}
@UiThreadTest
@@ -264,7 +280,7 @@
assertSame(movementMethod, mTextView.getMovementMethod());
assertEquals(selectionStart, Selection.getSelectionStart(mTextView.getText()));
assertEquals(selectionEnd, Selection.getSelectionEnd(mTextView.getText()));
- sendKeys(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_ALT_LEFT,
+ mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_ALT_LEFT,
KeyEvent.KEYCODE_DPAD_UP);
// the selection has been removed.
assertEquals(selectionStart, Selection.getSelectionStart(mTextView.getText()));
@@ -283,7 +299,7 @@
assertNull(mTextView.getMovementMethod());
assertEquals(selectionStart, Selection.getSelectionStart(mTextView.getText()));
assertEquals(selectionEnd, Selection.getSelectionEnd(mTextView.getText()));
- sendKeys(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_ALT_LEFT,
+ mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_ALT_LEFT,
KeyEvent.KEYCODE_DPAD_UP);
// the selection will not be changed.
assertEquals(selectionStart, Selection.getSelectionStart(mTextView.getText()));
@@ -470,38 +486,78 @@
}
}
- public void testSetHighlightColor() {
- mTextView = new TextView(mActivity);
+ public void testAccessHighlightColor() {
+ final TextView textView = (TextView) mActivity.findViewById(R.id.textview_text);
- mTextView.setHighlightColor(0x00ff00ff);
+ mActivity.runOnUiThread(() -> {
+ textView.setTextIsSelectable(true);
+ textView.setText("abcd", BufferType.EDITABLE);
+ textView.setHighlightColor(Color.BLUE);
+ });
+ mInstrumentation.waitForIdleSync();
+
+ assertTrue(textView.isTextSelectable());
+ assertEquals(Color.BLUE, textView.getHighlightColor());
+
+ // Long click on the text selects all text and shows selection handlers. The view has an
+ // attribute layout_width="wrap_content", so clicked location (the center of the view)
+ // should be on the text.
+ TouchUtils.longClickView(this, textView);
+
+ // At this point the entire content of our TextView should be selected and highlighted
+ // with blue. Now change the highlight to red while the selection is still on.
+ mActivity.runOnUiThread(() -> textView.setHighlightColor(Color.RED));
+ mInstrumentation.waitForIdleSync();
+
+ assertEquals(Color.RED, textView.getHighlightColor());
+ assertTrue(TextUtils.equals("abcd", textView.getText()));
+
+ // Remove the selection
+ mActivity.runOnUiThread(() -> Selection.removeSelection((Spannable) textView.getText()));
+ mInstrumentation.waitForIdleSync();
+
+ // And switch highlight to green after the selection has been removed
+ mActivity.runOnUiThread(() -> textView.setHighlightColor(Color.GREEN));
+ mInstrumentation.waitForIdleSync();
+
+ assertEquals(Color.GREEN, textView.getHighlightColor());
+ assertTrue(TextUtils.equals("abcd", textView.getText()));
}
+ @MediumTest
public void testSetShadowLayer() {
- MockTextView textView = new MockTextView(mActivity);
+ // test values
+ final MockTextView mockTextView = new MockTextView(mActivity);
+
+ mockTextView.setShadowLayer(1.0f, 0.3f, 0.4f, Color.CYAN);
+ assertEquals(Color.CYAN, mockTextView.getShadowColor());
+ assertEquals(0.3f, mockTextView.getShadowDx());
+ assertEquals(0.4f, mockTextView.getShadowDy());
+ assertEquals(1.0f, mockTextView.getShadowRadius());
// shadow is placed to the left and below the text
- textView.setShadowLayer(1.0f, 0.3f, 0.3f, Color.CYAN);
- assertTrue(textView.isPaddingOffsetRequired());
- assertEquals(0, textView.getLeftPaddingOffset());
- assertEquals(0, textView.getTopPaddingOffset());
- assertEquals(1, textView.getRightPaddingOffset());
- assertEquals(1, textView.getBottomPaddingOffset());
+ mockTextView.setShadowLayer(1.0f, 0.3f, 0.3f, Color.CYAN);
+ assertTrue(mockTextView.isPaddingOffsetRequired());
+ assertEquals(0, mockTextView.getLeftPaddingOffset());
+ assertEquals(0, mockTextView.getTopPaddingOffset());
+ assertEquals(1, mockTextView.getRightPaddingOffset());
+ assertEquals(1, mockTextView.getBottomPaddingOffset());
// shadow is placed to the right and above the text
- textView.setShadowLayer(1.0f, -0.8f, -0.8f, Color.CYAN);
- assertTrue(textView.isPaddingOffsetRequired());
- assertEquals(-1, textView.getLeftPaddingOffset());
- assertEquals(-1, textView.getTopPaddingOffset());
- assertEquals(0, textView.getRightPaddingOffset());
- assertEquals(0, textView.getBottomPaddingOffset());
+ mockTextView.setShadowLayer(1.0f, -0.8f, -0.8f, Color.CYAN);
+ assertTrue(mockTextView.isPaddingOffsetRequired());
+ assertEquals(-1, mockTextView.getLeftPaddingOffset());
+ assertEquals(-1, mockTextView.getTopPaddingOffset());
+ assertEquals(0, mockTextView.getRightPaddingOffset());
+ assertEquals(0, mockTextView.getBottomPaddingOffset());
// no shadow
- textView.setShadowLayer(0.0f, 0.0f, 0.0f, Color.CYAN);
- assertFalse(textView.isPaddingOffsetRequired());
- assertEquals(0, textView.getLeftPaddingOffset());
- assertEquals(0, textView.getTopPaddingOffset());
- assertEquals(0, textView.getRightPaddingOffset());
- assertEquals(0, textView.getBottomPaddingOffset());
+ mockTextView.setShadowLayer(0.0f, 0.0f, 0.0f, Color.CYAN);
+ assertFalse(mockTextView.isPaddingOffsetRequired());
+ assertEquals(0, mockTextView.getLeftPaddingOffset());
+ assertEquals(0, mockTextView.getTopPaddingOffset());
+ assertEquals(0, mockTextView.getRightPaddingOffset());
+ assertEquals(0, mockTextView.getBottomPaddingOffset());
}
@UiThreadTest
@@ -675,114 +731,199 @@
mTextView.getPaintFlags());
}
- public void testHeightAndWidth() {
+ @MediumTest
+ public void testHeight() {
mTextView = findTextView(R.id.textview_text);
- int originalWidth = mTextView.getWidth();
- setWidth(mTextView.getWidth() >> 3);
- int originalHeight = mTextView.getHeight();
+ final int originalHeight = mTextView.getHeight();
- setMaxHeight(originalHeight + 1);
+ // test setMaxHeight
+ int newHeight = originalHeight + 1;
+ setMaxHeight(newHeight);
assertEquals(originalHeight, mTextView.getHeight());
+ assertEquals(newHeight, mTextView.getMaxHeight());
- setMaxHeight(originalHeight - 1);
- assertEquals(originalHeight - 1, mTextView.getHeight());
+ newHeight = originalHeight - 1;
+ setMaxHeight(newHeight);
+ assertEquals(newHeight, mTextView.getHeight());
+ assertEquals(newHeight, mTextView.getMaxHeight());
- setMaxHeight(-1);
+ newHeight = -1;
+ setMaxHeight(newHeight);
assertEquals(0, mTextView.getHeight());
+ assertEquals(newHeight, mTextView.getMaxHeight());
- setMaxHeight(Integer.MAX_VALUE);
+ newHeight = Integer.MAX_VALUE;
+ setMaxHeight(newHeight);
assertEquals(originalHeight, mTextView.getHeight());
+ assertEquals(newHeight, mTextView.getMaxHeight());
- setMinHeight(originalHeight + 1);
- assertEquals(originalHeight + 1, mTextView.getHeight());
+ // test setMinHeight
+ newHeight = originalHeight + 1;
+ setMinHeight(newHeight);
+ assertEquals(newHeight, mTextView.getHeight());
+ assertEquals(newHeight, mTextView.getMinHeight());
- setMinHeight(originalHeight - 1);
+ newHeight = originalHeight - 1;
+ setMinHeight(newHeight);
assertEquals(originalHeight, mTextView.getHeight());
+ assertEquals(newHeight, mTextView.getMinHeight());
- setMinHeight(-1);
+ newHeight = -1;
+ setMinHeight(newHeight);
assertEquals(originalHeight, mTextView.getHeight());
+ assertEquals(newHeight, mTextView.getMinHeight());
+ // reset min and max height
setMinHeight(0);
setMaxHeight(Integer.MAX_VALUE);
- setHeight(originalHeight + 1);
- assertEquals(originalHeight + 1, mTextView.getHeight());
+ // test setHeight
+ newHeight = originalHeight + 1;
+ setHeight(newHeight);
+ assertEquals(newHeight, mTextView.getHeight());
+ assertEquals(newHeight, mTextView.getMaxHeight());
+ assertEquals(newHeight, mTextView.getMinHeight());
- setHeight(originalHeight - 1);
- assertEquals(originalHeight - 1, mTextView.getHeight());
+ newHeight = originalHeight - 1;
+ setHeight(newHeight);
+ assertEquals(newHeight, mTextView.getHeight());
+ assertEquals(newHeight, mTextView.getMaxHeight());
+ assertEquals(newHeight, mTextView.getMinHeight());
- setHeight(-1);
+ newHeight = -1;
+ setHeight(newHeight);
assertEquals(0, mTextView.getHeight());
+ assertEquals(newHeight, mTextView.getMaxHeight());
+ assertEquals(newHeight, mTextView.getMinHeight());
setHeight(originalHeight);
assertEquals(originalHeight, mTextView.getHeight());
+ assertEquals(originalHeight, mTextView.getMaxHeight());
+ assertEquals(originalHeight, mTextView.getMinHeight());
- assertEquals(originalWidth >> 3, mTextView.getWidth());
+ // setting max/min lines should cause getMaxHeight/getMinHeight to return -1
+ setMaxLines(2);
+ assertEquals("Setting maxLines should return -1 fir maxHeight",
+ -1, mTextView.getMaxHeight());
- // Min Width
- setMinWidth(originalWidth + 1);
- assertEquals(1, mTextView.getLineCount());
- assertEquals(originalWidth + 1, mTextView.getWidth());
-
- setMinWidth(originalWidth - 1);
- assertEquals(2, mTextView.getLineCount());
- assertEquals(originalWidth - 1, mTextView.getWidth());
-
- // Width
- setWidth(originalWidth + 1);
- assertEquals(1, mTextView.getLineCount());
- assertEquals(originalWidth + 1, mTextView.getWidth());
-
- setWidth(originalWidth - 1);
- assertEquals(2, mTextView.getLineCount());
- assertEquals(originalWidth - 1, mTextView.getWidth());
+ setMinLines(1);
+ assertEquals("Setting minLines should return -1 for minHeight",
+ -1, mTextView.getMinHeight());
}
+ @MediumTest
+ public void testWidth() {
+ mTextView = findTextView(R.id.textview_text);
+ int originalWidth = mTextView.getWidth();
+
+ int newWidth = mTextView.getWidth() / 8;
+ setWidth(newWidth);
+ assertEquals(newWidth, mTextView.getWidth());
+ assertEquals(newWidth, mTextView.getMaxWidth());
+ assertEquals(newWidth, mTextView.getMinWidth());
+
+ // Min Width
+ newWidth = originalWidth + 1;
+ setMinWidth(newWidth);
+ assertEquals(1, mTextView.getLineCount());
+ assertEquals(newWidth, mTextView.getWidth());
+ assertEquals(newWidth, mTextView.getMinWidth());
+
+ newWidth = originalWidth - 1;
+ setMinWidth(originalWidth - 1);
+ assertEquals(2, mTextView.getLineCount());
+ assertEquals(newWidth, mTextView.getWidth());
+ assertEquals(newWidth, mTextView.getMinWidth());
+
+ // Width
+ newWidth = originalWidth + 1;
+ setWidth(newWidth);
+ assertEquals(1, mTextView.getLineCount());
+ assertEquals(newWidth, mTextView.getWidth());
+ assertEquals(newWidth, mTextView.getMaxWidth());
+ assertEquals(newWidth, mTextView.getMinWidth());
+
+ newWidth = originalWidth - 1;
+ setWidth(newWidth);
+ assertEquals(2, mTextView.getLineCount());
+ assertEquals(newWidth, mTextView.getWidth());
+ assertEquals(newWidth, mTextView.getMaxWidth());
+ assertEquals(newWidth, mTextView.getMinWidth());
+
+ // setting ems should cause getMaxWidth/getMinWidth to return -1
+ setEms(1);
+ assertEquals("Setting ems should return -1 for maxWidth", -1, mTextView.getMaxWidth());
+ assertEquals("Setting ems should return -1 for maxWidth", -1, mTextView.getMinWidth());
+ }
+
+ @MediumTest
public void testSetMinEms() {
mTextView = findTextView(R.id.textview_text);
assertEquals(1, mTextView.getLineCount());
- int originalWidth = mTextView.getWidth();
- int originalEms = originalWidth / mTextView.getLineHeight();
+ final int originalWidth = mTextView.getWidth();
+ final int originalEms = originalWidth / mTextView.getLineHeight();
setMinEms(originalEms + 1);
assertEquals((originalEms + 1) * mTextView.getLineHeight(), mTextView.getWidth());
+ assertEquals(-1, mTextView.getMinWidth());
+ assertEquals(originalEms + 1, mTextView.getMinEms());
setMinEms(originalEms - 1);
assertEquals(originalWidth, mTextView.getWidth());
+ assertEquals(-1, mTextView.getMinWidth());
+ assertEquals(originalEms - 1, mTextView.getMinEms());
+
+ setMinWidth(1);
+ assertEquals(-1, mTextView.getMinEms());
}
+ @MediumTest
public void testSetMaxEms() {
mTextView = findTextView(R.id.textview_text);
assertEquals(1, mTextView.getLineCount());
- int originalWidth = mTextView.getWidth();
- int originalEms = originalWidth / mTextView.getLineHeight();
+
+ final int originalWidth = mTextView.getWidth();
+ final int originalEms = originalWidth / mTextView.getLineHeight();
setMaxEms(originalEms + 1);
assertEquals(1, mTextView.getLineCount());
assertEquals(originalWidth, mTextView.getWidth());
+ assertEquals(-1, mTextView.getMaxWidth());
+ assertEquals(originalEms + 1, mTextView.getMaxEms());
setMaxEms(originalEms - 1);
assertTrue(1 < mTextView.getLineCount());
- assertEquals((originalEms - 1) * mTextView.getLineHeight(),
- mTextView.getWidth());
+ assertEquals((originalEms - 1) * mTextView.getLineHeight(), mTextView.getWidth());
+ assertEquals(-1, mTextView.getMaxWidth());
+ assertEquals(originalEms - 1, mTextView.getMaxEms());
+
+ setMaxWidth(originalWidth);
+ assertEquals(-1, mTextView.getMaxEms());
}
+ @MediumTest
public void testSetEms() {
mTextView = findTextView(R.id.textview_text);
assertEquals("check height", 1, mTextView.getLineCount());
- int originalWidth = mTextView.getWidth();
- int originalEms = originalWidth / mTextView.getLineHeight();
+ final int originalWidth = mTextView.getWidth();
+ final int originalEms = originalWidth / mTextView.getLineHeight();
setEms(originalEms + 1);
assertEquals(1, mTextView.getLineCount());
- assertEquals((originalEms + 1) * mTextView.getLineHeight(),
- mTextView.getWidth());
+ assertEquals((originalEms + 1) * mTextView.getLineHeight(), mTextView.getWidth());
+ assertEquals(-1, mTextView.getMinWidth());
+ assertEquals(-1, mTextView.getMaxWidth());
+ assertEquals(originalEms + 1, mTextView.getMinEms());
+ assertEquals(originalEms + 1, mTextView.getMaxEms());
setEms(originalEms - 1);
assertTrue((1 < mTextView.getLineCount()));
- assertEquals((originalEms - 1) * mTextView.getLineHeight(),
- mTextView.getWidth());
+ assertEquals((originalEms - 1) * mTextView.getLineHeight(), mTextView.getWidth());
+ assertEquals(-1, mTextView.getMinWidth());
+ assertEquals(-1, mTextView.getMaxWidth());
+ assertEquals(originalEms - 1, mTextView.getMinEms());
+ assertEquals(originalEms - 1, mTextView.getMaxEms());
}
public void testSetLineSpacing() {
@@ -949,31 +1090,30 @@
public void testSetEditableFactory() {
mTextView = new TextView(mActivity);
String text = "sample";
- MockEditableFactory factory = new MockEditableFactory();
- mTextView.setEditableFactory(factory);
- factory.reset();
+ final Editable.Factory mockEditableFactory = spy(new Editable.Factory());
+ doCallRealMethod().when(mockEditableFactory).newEditable(any(CharSequence.class));
+ mTextView.setEditableFactory(mockEditableFactory);
+
mTextView.setText(text);
- assertFalse(factory.hasCalledNewEditable());
+ verify(mockEditableFactory, never()).newEditable(any(CharSequence.class));
- factory.reset();
+ reset(mockEditableFactory);
mTextView.setText(text, BufferType.SPANNABLE);
- assertFalse(factory.hasCalledNewEditable());
+ verify(mockEditableFactory, never()).newEditable(any(CharSequence.class));
- factory.reset();
+ reset(mockEditableFactory);
mTextView.setText(text, BufferType.NORMAL);
- assertFalse(factory.hasCalledNewEditable());
+ verify(mockEditableFactory, never()).newEditable(any(CharSequence.class));
- factory.reset();
+ reset(mockEditableFactory);
mTextView.setText(text, BufferType.EDITABLE);
- assertTrue(factory.hasCalledNewEditable());
- assertEquals(text, factory.getSource());
+ verify(mockEditableFactory, times(1)).newEditable(text);
mTextView.setKeyListener(DigitsKeyListener.getInstance());
- factory.reset();
+ reset(mockEditableFactory);
mTextView.setText(text, BufferType.EDITABLE);
- assertTrue(factory.hasCalledNewEditable());
- assertEquals(text, factory.getSource());
+ verify(mockEditableFactory, times(1)).newEditable(text);
try {
mTextView.setEditableFactory(null);
@@ -985,31 +1125,30 @@
public void testSetSpannableFactory() {
mTextView = new TextView(mActivity);
String text = "sample";
- MockSpannableFactory factory = new MockSpannableFactory();
- mTextView.setSpannableFactory(factory);
- factory.reset();
+ final Spannable.Factory mockSpannableFactory = spy(new Spannable.Factory());
+ doCallRealMethod().when(mockSpannableFactory).newSpannable(any(CharSequence.class));
+ mTextView.setSpannableFactory(mockSpannableFactory);
+
mTextView.setText(text);
- assertFalse(factory.hasCalledNewSpannable());
+ verify(mockSpannableFactory, never()).newSpannable(any(CharSequence.class));
- factory.reset();
+ reset(mockSpannableFactory);
mTextView.setText(text, BufferType.EDITABLE);
- assertFalse(factory.hasCalledNewSpannable());
+ verify(mockSpannableFactory, never()).newSpannable(any(CharSequence.class));
- factory.reset();
+ reset(mockSpannableFactory);
mTextView.setText(text, BufferType.NORMAL);
- assertFalse(factory.hasCalledNewSpannable());
+ verify(mockSpannableFactory, never()).newSpannable(any(CharSequence.class));
- factory.reset();
+ reset(mockSpannableFactory);
mTextView.setText(text, BufferType.SPANNABLE);
- assertTrue(factory.hasCalledNewSpannable());
- assertEquals(text, factory.getSource());
+ verify(mockSpannableFactory, times(1)).newSpannable(text);
mTextView.setMovementMethod(LinkMovementMethod.getInstance());
- factory.reset();
+ reset(mockSpannableFactory);
mTextView.setText(text, BufferType.NORMAL);
- assertTrue(factory.hasCalledNewSpannable());
- assertEquals(text, factory.getSource());
+ verify(mockSpannableFactory, times(1)).newSpannable(text);
try {
mTextView.setSpannableFactory(null);
@@ -1374,29 +1513,25 @@
public void testRemoveSelectionWithSelectionHandles() {
initTextViewForTyping();
- mActivity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mTextView.setTextIsSelectable(true);
- mTextView.setText("abcd", BufferType.EDITABLE);
- }
+ assertFalse(mTextView.isTextSelectable());
+ mActivity.runOnUiThread(() -> {
+ mTextView.setTextIsSelectable(true);
+ mTextView.setText("abcd", BufferType.EDITABLE);
});
mInstrumentation.waitForIdleSync();
+ assertTrue(mTextView.isTextSelectable());
// Long click on the text selects all text and shows selection handlers. The view has an
// attribute layout_width="wrap_content", so clicked location (the center of the view)
// should be on the text.
TouchUtils.longClickView(this, mTextView);
- mActivity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Selection.removeSelection((Spannable) mTextView.getText());
- }
- });
+ mActivity.runOnUiThread(() -> Selection.removeSelection((Spannable) mTextView.getText()));
// Make sure that a crash doesn't happen with {@link Selection#removeSelection}.
mInstrumentation.waitForIdleSync();
+
+ assertTrue(TextUtils.equals("abcd", mTextView.getText()));
}
public void testUndo_insert() {
@@ -1838,7 +1973,7 @@
initTextViewForTyping();
// Type "abc".
- mInstrumentation.sendStringSync("abc");
+ mKeyEventUtil.sendString(mTextView, "abc");
mActivity.runOnUiThread(new Runnable() {
public void run() {
// Select "bc"
@@ -1847,7 +1982,7 @@
});
mInstrumentation.waitForIdleSync();
// Copy "bc"
- sendKeys(KeyEvent.KEYCODE_COPY);
+ mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_COPY);
mActivity.runOnUiThread(new Runnable() {
public void run() {
@@ -1857,7 +1992,7 @@
});
mInstrumentation.waitForIdleSync();
// Paste "bc"
- sendKeys(KeyEvent.KEYCODE_PASTE);
+ mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_PASTE);
assertEquals("abbcc", mTextView.getText().toString());
mActivity.runOnUiThread(new Runnable() {
@@ -1922,7 +2057,7 @@
initTextViewForTyping();
// Type "abc".
- mInstrumentation.sendStringSync("abc");
+ mKeyEventUtil.sendString(mTextView, "abc");
mActivity.runOnUiThread(new Runnable() {
public void run() {
// Select "bc"
@@ -1931,7 +2066,7 @@
});
mInstrumentation.waitForIdleSync();
// Cut "bc"
- sendKeys(KeyEvent.KEYCODE_CUT);
+ mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_CUT);
mActivity.runOnUiThread(new Runnable() {
public void run() {
@@ -1942,7 +2077,7 @@
});
mInstrumentation.waitForIdleSync();
// Paste "bc"
- sendKeys(KeyEvent.KEYCODE_PASTE);
+ mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_PASTE);
assertEquals("bca", mTextView.getText().toString());
mActivity.runOnUiThread(new Runnable() {
@@ -2223,7 +2358,7 @@
assertEquals(errorText, mTextView.getError().toString());
- mInstrumentation.sendStringSync("a");
+ mKeyEventUtil.sendString(mTextView, "a");
// a key event that will not change the TextView's text
assertEquals("", mTextView.getText().toString());
// The icon and error message will not be reset to null
@@ -2239,7 +2374,7 @@
});
mInstrumentation.waitForIdleSync();
- mInstrumentation.sendStringSync("1");
+ mKeyEventUtil.sendString(mTextView, "1");
// a key event cause changes to the TextView's text
assertEquals("1", mTextView.getText().toString());
// the error message and icon will be cleared.
@@ -2265,13 +2400,13 @@
assertSame(expected, mTextView.getFilters());
- mInstrumentation.sendStringSync("a");
+ mKeyEventUtil.sendString(mTextView, "a");
// the text is capitalized by InputFilter.AllCaps
assertEquals("A", mTextView.getText().toString());
- mInstrumentation.sendStringSync("b");
+ mKeyEventUtil.sendString(mTextView, "b");
// the text is capitalized by InputFilter.AllCaps
assertEquals("AB", mTextView.getText().toString());
- mInstrumentation.sendStringSync("c");
+ mKeyEventUtil.sendString(mTextView, "c");
// 'C' could not be accepted, because there is a length filter.
assertEquals("AB", mTextView.getText().toString());
@@ -2468,11 +2603,11 @@
public void testPressKey() {
initTextViewForTyping();
- mInstrumentation.sendStringSync("a");
+ mKeyEventUtil.sendString(mTextView, "a");
assertEquals("a", mTextView.getText().toString());
- mInstrumentation.sendStringSync("b");
+ mKeyEventUtil.sendString(mTextView, "b");
assertEquals("ab", mTextView.getText().toString());
- sendKeys(KeyEvent.KEYCODE_DEL);
+ mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_DEL);
assertEquals("a", mTextView.getText().toString());
}
@@ -2557,6 +2692,53 @@
assertTrue(mTextView.hasSelection());
}
+ @MediumTest
+ public void testOnSelectionChanged_isTriggeredWhenSelectionChanges() {
+ final MockTextView textView = new MockTextView(mActivity);
+ final String text = "any text";
+ textView.setText(text, BufferType.SPANNABLE);
+
+ // assert that there is currently no selection
+ assertFalse(textView.hasSelection());
+
+ // select all
+ Selection.selectAll((Spannable) textView.getText());
+
+ assertTrue("After selectAll OnSelectionChanged should have been called",
+ textView.hasCalledOnSelectionChanged());
+ assertEquals("OnSelectionChanged should have been called with 0 for selection start",
+ 0, textView.getSelectionChangedStart());
+ assertEquals("OnSelectionChanged should have been called with text length for "
+ + "selection end",
+ text.length(), textView.getSelectionChangedEnd());
+
+ // reset MockTextView selection flags
+ textView.reset();
+
+ // change selection
+ Selection.setSelection((Spannable) textView.getText(), 1, 5);
+
+ assertTrue("OnSelectionChanged should have been called",
+ textView.hasCalledOnSelectionChanged());
+ assertEquals("OnSelectionChanged should have been called with 1 for selection start",
+ 1, textView.getSelectionChangedStart());
+ assertEquals("OnSelectionChanged should have been called with -1 for selection end",
+ 5, textView.getSelectionChangedEnd());
+
+ // reset MockTextView selection flags
+ textView.reset();
+
+ // clear selection
+ Selection.removeSelection((Spannable) textView.getText());
+
+ assertTrue("OnSelectionChanged should have been called",
+ textView.hasCalledOnSelectionChanged());
+ assertEquals("OnSelectionChanged should have been called with -1 for selection start",
+ -1, textView.getSelectionChangedStart());
+ assertEquals("OnSelectionChanged should have been called with -1 for selection end",
+ -1, textView.getSelectionChangedEnd());
+ }
+
@UiThreadTest
public void testAccessEllipsize() {
mActivity.setContentView(R.layout.textview_ellipsize);
@@ -2671,11 +2853,61 @@
}
}
- public void testSetCursorVisible() {
+ public void testTextViewInWeigthenedLayoutChangesWidthAfterSetText() {
+ final TextView textView = new TextView(getActivity());
+ textView.setEllipsize(TruncateAt.END);
+ textView.setSingleLine(true);
+ textView.setText("a");
+
+ TextView otherTextView = new TextView(getActivity());
+ otherTextView.setSingleLine(true);
+ otherTextView.setText("any");
+
+ final LinearLayout layout = new LinearLayout(mActivity);
+ layout.setOrientation(LinearLayout.HORIZONTAL);
+
+ // TextView under test has weight 1, and width 0
+ layout.addView(textView, new LinearLayout.LayoutParams(0,
+ ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f));
+
+ // other TextView has default weight
+ layout.addView(otherTextView, new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+
+ // main layout params
+ layout.setLayoutParams(new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getActivity().setContentView(layout);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+
+ int oldWidth = textView.getWidth();
+
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ textView.setText("aaa");
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+
+ assertTrue("TextView should have larger width after a longer text is set",
+ textView.getWidth() > oldWidth);
+ }
+
+ public void testAccessCursorVisible() {
mTextView = new TextView(mActivity);
mTextView.setCursorVisible(true);
+ assertTrue(mTextView.isCursorVisible());
mTextView.setCursorVisible(false);
+ assertFalse(mTextView.isCursorVisible());
}
public void testOnWindowFocusChanged() {
@@ -2702,27 +2934,39 @@
public void testPerformLongClick() {
mTextView = findTextView(R.id.textview_text);
mTextView.setText("This is content");
- MockOnLongClickListener onLongClickListener = new MockOnLongClickListener(true);
- MockOnCreateContextMenuListener onCreateContextMenuListener
- = new MockOnCreateContextMenuListener(false);
- mTextView.setOnLongClickListener(onLongClickListener);
- mTextView.setOnCreateContextMenuListener(onCreateContextMenuListener);
- assertTrue(mTextView.performLongClick());
- assertTrue(onLongClickListener.hasLongClicked());
- assertFalse(onCreateContextMenuListener.hasCreatedContextMenu());
- onLongClickListener = new MockOnLongClickListener(false);
- mTextView.setOnLongClickListener(onLongClickListener);
- mTextView.setOnCreateContextMenuListener(onCreateContextMenuListener);
- assertTrue(mTextView.performLongClick());
- assertTrue(onLongClickListener.hasLongClicked());
- assertTrue(onCreateContextMenuListener.hasCreatedContextMenu());
+ View.OnLongClickListener mockOnLongClickListener = mock(View.OnLongClickListener.class);
+ when(mockOnLongClickListener.onLongClick(any(View.class))).thenReturn(Boolean.TRUE);
+ View.OnCreateContextMenuListener mockOnCreateContextMenuListener =
+ mock(View.OnCreateContextMenuListener.class);
+ doAnswer((InvocationOnMock invocation) -> {
+ ((ContextMenu) invocation.getArguments() [0]).add("menu item");
+ return null;
+ }).when(mockOnCreateContextMenuListener).onCreateContextMenu(
+ any(ContextMenu.class), any(View.class), any(ContextMenuInfo.class));
+
+ mTextView.setOnLongClickListener(mockOnLongClickListener);
+ mTextView.setOnCreateContextMenuListener(mockOnCreateContextMenuListener);
+ assertTrue(mTextView.performLongClick());
+ verify(mockOnLongClickListener, times(1)).onLongClick(mTextView);
+ verifyZeroInteractions(mockOnCreateContextMenuListener);
+
+ reset(mockOnLongClickListener);
+ when(mockOnLongClickListener.onLongClick(any(View.class))).thenReturn(Boolean.FALSE);
+ assertTrue(mTextView.performLongClick());
+ verify(mockOnLongClickListener, times(1)).onLongClick(mTextView);
+ verify(mockOnCreateContextMenuListener, times(1)).onCreateContextMenu(
+ any(ContextMenu.class), eq(mTextView), any(ContextMenuInfo.class));
+
+ reset(mockOnCreateContextMenuListener);
mTextView.setOnLongClickListener(null);
- onCreateContextMenuListener = new MockOnCreateContextMenuListener(true);
- mTextView.setOnCreateContextMenuListener(onCreateContextMenuListener);
+ doNothing().when(mockOnCreateContextMenuListener).onCreateContextMenu(
+ any(ContextMenu.class), any(View.class), any(ContextMenuInfo.class));
assertFalse(mTextView.performLongClick());
- assertTrue(onCreateContextMenuListener.hasCreatedContextMenu());
+ verifyNoMoreInteractions(mockOnLongClickListener);
+ verify(mockOnCreateContextMenuListener, times(1)).onCreateContextMenu(
+ any(ContextMenu.class), eq(mTextView), any(ContextMenuInfo.class));
}
@UiThreadTest
@@ -2952,6 +3196,286 @@
urlSpans[0].getURL(), "http://android.com/textview");
}
+ @MediumTest
+ public void testGetLetterSpacing_returnsValueThatWasSet() {
+ mTextView = new TextView(mActivity);
+ mTextView.setLetterSpacing(2f);
+ assertEquals("getLetterSpacing should return the value that was set",
+ 2f, mTextView.getLetterSpacing());
+ }
+
+ @MediumTest
+ public void testSetLetterSpacing_changesTextWidth() {
+ final TextView textView = new TextView(mActivity);
+ textView.setText("aa");
+ textView.setLetterSpacing(0f);
+ textView.setTextSize(8f);
+
+ final FrameLayout layout = new FrameLayout(mActivity);
+ final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.MATCH_PARENT);
+ layout.addView(textView, layoutParams);
+ layout.setLayoutParams(layoutParams);
+
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getActivity().setContentView(layout);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+
+ // measure text with zero letter spacing
+ final float zeroSpacing = textView.getLayout().getLineWidth(0);
+
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ textView.setLetterSpacing(1f);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+
+ // measure text with single letter spacing
+ final float singleSpacing = textView.getLayout().getLineWidth(0);
+
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ textView.setLetterSpacing(2f);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+
+ // measure text with double letter spacing
+ final float doubleSpacing = textView.getLayout().getLineWidth(0);
+
+ assertEquals("Double spacing should have two times the spacing of single spacing",
+ doubleSpacing - zeroSpacing, 2f * (singleSpacing - zeroSpacing), 1f);
+ }
+
+ @MediumTest
+ public void testGetFontFeatureSettings_returnsValueThatWasSet() {
+ mTextView = new TextView(mActivity);
+ mTextView.setFontFeatureSettings("\"smcp\" on");
+ assertEquals("getFontFeatureSettings should return the value that was set",
+ "\"smcp\" on", mTextView.getFontFeatureSettings());
+ }
+
+ @MediumTest
+ public void testGetOffsetForPosition_singleLineLtr() {
+ // asserts getOffsetPosition returns correct values for a single line LTR text
+ String text = "aaaaa";
+ final TextView textView = new TextView(mActivity);
+ textView.setText(text);
+ textView.setTextSize(8f);
+ textView.setSingleLine(true);
+
+ // add a compound drawable to TextView to make offset calculation more interesting
+ final Drawable drawable = getDrawable(R.drawable.red);
+ drawable.setBounds(0, 0, 10, 10);
+ textView.setCompoundDrawables(drawable, drawable, drawable, drawable);
+
+ final FrameLayout layout = new FrameLayout(mActivity);
+ final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ layout.addView(textView, layoutParams);
+ layout.setLayoutParams(layoutParams);
+
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getActivity().setContentView(layout);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+
+ final int firstOffset = 0;
+ final int lastOffset = text.length() - 1;
+ final int midOffset = text.length() / 2;
+
+ // left edge of view
+ float x = 0f;
+ float y = textView.getHeight() / 2f;
+ assertEquals(firstOffset, textView.getOffsetForPosition(x, y));
+
+ // right edge of text
+ x = textView.getLayout().getLineWidth(0) - 1f;
+ assertEquals(lastOffset, textView.getOffsetForPosition(x, y));
+
+ // right edge of view
+ x = textView.getWidth();
+ assertEquals(lastOffset + 1, textView.getOffsetForPosition(x, y));
+
+ // left edge of view - out of bounds
+ x = -1f;
+ assertEquals(firstOffset, textView.getOffsetForPosition(x, y));
+
+ // horizontal center of text
+ x = textView.getLayout().getLineWidth(0) / 2f - 1f;
+ assertEquals(midOffset, textView.getOffsetForPosition(x, y));
+ }
+
+ @MediumTest
+ public void testGetOffsetForPosition_multiLineLtr() {
+ final String line = "aa\n";
+ final String threeLines = line + line + line;
+ final TextView textView = new TextView(mActivity);
+ textView.setText(threeLines);
+ textView.setTextSize(8f);
+ textView.setLines(2);
+
+ // add a compound drawable to TextView to make offset calculation more interesting
+ final Drawable drawable = getDrawable(R.drawable.red);
+ drawable.setBounds(0, 0, 10, 10);
+ textView.setCompoundDrawables(drawable, drawable, drawable, drawable);
+
+ final FrameLayout layout = new FrameLayout(mActivity);
+ final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ layout.addView(textView, layoutParams);
+ layout.setLayoutParams(layoutParams);
+
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getActivity().setContentView(layout);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+
+ final Rect lineBounds = new Rect();
+ textView.getLayout().getLineBounds(0, lineBounds);
+
+ // left edge of view at first line
+ float x = 0f;
+ float y = lineBounds.height() / 2f;
+ assertEquals(0, textView.getOffsetForPosition(x, y));
+
+ // right edge of view at first line
+ x = textView.getWidth() - 1f;
+ assertEquals(line.length() - 1, textView.getOffsetForPosition(x, y));
+
+ // update lineBounds to be the second line
+ textView.getLayout().getLineBounds(1, lineBounds);
+ y = lineBounds.top + lineBounds.height() / 2;
+
+ // left edge of view at second line
+ x = 0f;
+ assertEquals(line.length(), textView.getOffsetForPosition(x, y));
+
+ // right edge of text at second line
+ x = textView.getLayout().getLineWidth(1) - 1f;
+ assertEquals(line.length() + line.length() - 1, textView.getOffsetForPosition(x, y));
+
+ // right edge of view at second line
+ x = textView.getWidth() - 1f;
+ assertEquals(line.length() + line.length() - 1, textView.getOffsetForPosition(x, y));
+
+ // horizontal center of text at second line
+ x = textView.getLayout().getLineWidth(1) / 2f;
+ assertEquals(line.length() + line.length() / 2, textView.getOffsetForPosition(x, y));
+ }
+
+ @MediumTest
+ public void testGetOffsetForPosition_multiLineRtl() {
+ final String line = "\u0635\u0635\n";
+ final String threeLines = line + line + line;
+ final TextView textView = new TextView(mActivity);
+ textView.setText(threeLines);
+ textView.setTextSize(8f);
+ textView.setLines(2);
+
+ // add a compound drawable to TextView to make offset calculation more interesting
+ final Drawable drawable = getDrawable(R.drawable.red);
+ drawable.setBounds(0, 0, 10, 10);
+ textView.setCompoundDrawables(drawable, drawable, drawable, drawable);
+
+ final FrameLayout layout = new FrameLayout(mActivity);
+ final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ layout.addView(textView, layoutParams);
+ layout.setLayoutParams(layoutParams);
+
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getActivity().setContentView(layout);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
+
+ final Rect lineBounds = new Rect();
+ textView.getLayout().getLineBounds(0, lineBounds);
+
+ // right edge of view at first line
+ float x = textView.getWidth() - 1f;
+ float y = lineBounds.height() / 2f;
+ assertEquals(0, textView.getOffsetForPosition(x, y));
+
+ // left edge of view at first line
+ x = 0f;
+ assertEquals(line.length() - 1, textView.getOffsetForPosition(x, y));
+
+ // update lineBounds to be the second line
+ textView.getLayout().getLineBounds(1, lineBounds);
+ y = lineBounds.top + lineBounds.height() / 2f;
+
+ // right edge of view at second line
+ x = textView.getWidth() - 1f;
+ assertEquals(line.length(), textView.getOffsetForPosition(x, y));
+
+ // left edge of view at second line
+ x = 0f;
+ assertEquals(line.length() + line.length() - 1, textView.getOffsetForPosition(x, y));
+
+ // right edge of text at second line
+ x = textView.getWidth() - textView.getLayout().getLineWidth(1) + 1f;
+ assertEquals(line.length() + line.length() - 1, textView.getOffsetForPosition(x, y));
+
+ // horizontal center of text at second line
+ x = textView.getWidth() - (textView.getLayout().getLineWidth(1) / 2f);
+ assertEquals(line.length() + line.length() / 2, textView.getOffsetForPosition(x, y));
+ }
+
+ @MediumTest
+ public void testIsTextSelectable_returnsFalseByDefault() {
+ final TextView textView = new TextView(getActivity());
+ textView.setText("any text");
+ assertFalse(textView.isTextSelectable());
+ }
+
+ @MediumTest
+ public void testIsTextSelectable_returnsTrueIfSetTextIsSelectableCalledWithTrue() {
+ final TextView textView = new TextView(getActivity());
+ textView.setText("any text");
+ textView.setTextIsSelectable(true);
+ assertTrue(textView.isTextSelectable());
+ }
+
+ @MediumTest
+ public void testSetIsTextSelectable() {
+ final TextView textView = new TextView(getActivity());
+
+ assertFalse(textView.isTextSelectable());
+ assertFalse(textView.isFocusable());
+ assertFalse(textView.isFocusableInTouchMode());
+ assertFalse(textView.isClickable());
+ assertFalse(textView.isLongClickable());
+
+ textView.setTextIsSelectable(true);
+
+ assertTrue(textView.isTextSelectable());
+ assertTrue(textView.isFocusable());
+ assertTrue(textView.isFocusableInTouchMode());
+ assertTrue(textView.isClickable());
+ assertTrue(textView.isLongClickable());
+ assertNotNull(textView.getMovementMethod());
+ }
public void testAccessTransformationMethod() {
// check the password attribute in xml
@@ -2983,7 +3507,7 @@
assertSame(PasswordTransformationMethod.getInstance(),
mTextView.getTransformationMethod());
- sendKeys("H E 2*L O");
+ mKeyEventUtil.sendKeys(mTextView, "H E 2*L O");
mActivity.runOnUiThread(new Runnable() {
public void run() {
mTextView.append(" ");
@@ -2991,15 +3515,10 @@
});
mInstrumentation.waitForIdleSync();
- // it will get transformed after a while
- new PollingCheck(TIMEOUT) {
- @Override
- protected boolean check() {
- // "******"
- return mTransformedText.toString()
- .equals("\u2022\u2022\u2022\u2022\u2022\u2022");
- }
- }.run();
+ // It will get transformed after a while
+ // We're waiting for transformation to "******"
+ PollingCheck.waitFor(TIMEOUT, () -> mTransformedText.toString()
+ .equals("\u2022\u2022\u2022\u2022\u2022\u2022"));
// set null
mActivity.runOnUiThread(new Runnable() {
@@ -3095,13 +3614,71 @@
assertEquals(mTextView.getPaddingBottom(), mTextView.getCompoundPaddingBottom());
}
+ @MediumTest
+ @UiThreadTest
+ public void testGetCompoundDrawablesRelative() {
+ // prepare textview
+ mTextView = new TextView(mActivity);
+
+ // prepare drawables
+ final Drawable start = getDrawable(R.drawable.blue);
+ final Drawable end = getDrawable(R.drawable.yellow);
+ final Drawable top = getDrawable(R.drawable.red);
+ final Drawable bottom = getDrawable(R.drawable.black);
+ assertNotNull(start);
+ assertNotNull(end);
+ assertNotNull(top);
+ assertNotNull(bottom);
+
+ Drawable[] drawables = mTextView.getCompoundDrawablesRelative();
+ assertNotNull(drawables);
+ assertEquals(4, drawables.length);
+ assertNull(drawables[0]);
+ assertNull(drawables[1]);
+ assertNull(drawables[2]);
+ assertNull(drawables[3]);
+
+ mTextView.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
+ mTextView.setCompoundDrawablesRelative(start, top, end, bottom);
+ drawables = mTextView.getCompoundDrawablesRelative();
+
+ assertNotNull(drawables);
+ assertEquals(4, drawables.length);
+ assertSame(start, drawables[0]);
+ assertSame(top, drawables[1]);
+ assertSame(end, drawables[2]);
+ assertSame(bottom, drawables[3]);
+
+ mTextView.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
+ mTextView.setCompoundDrawablesRelative(start, top, end, bottom);
+ drawables = mTextView.getCompoundDrawablesRelative();
+
+ assertNotNull(drawables);
+ assertEquals(4, drawables.length);
+ assertSame(start, drawables[0]);
+ assertSame(top, drawables[1]);
+ assertSame(end, drawables[2]);
+ assertSame(bottom, drawables[3]);
+
+ mTextView.setCompoundDrawablesRelative(null, null, null, null);
+ drawables = mTextView.getCompoundDrawablesRelative();
+
+ assertNotNull(drawables);
+ assertEquals(4, drawables.length);
+ assertNull(drawables[0]);
+ assertNull(drawables[1]);
+ assertNull(drawables[2]);
+ assertNull(drawables[3]);
+ }
+
+ @MediumTest
public void testSingleLine() {
final TextView textView = new TextView(mActivity);
setSpannableText(textView, "This is a really long sentence"
+ " which can not be placed in one line on the screen.");
// Narrow layout assures that the text will get wrapped.
- FrameLayout innerLayout = new FrameLayout(mActivity);
+ final FrameLayout innerLayout = new FrameLayout(mActivity);
innerLayout.setLayoutParams(new ViewGroup.LayoutParams(100, 100));
innerLayout.addView(textView);
@@ -3157,7 +3734,7 @@
}
@UiThreadTest
- public void testSetMaxLines() {
+ public void testAccessMaxLines() {
mTextView = findTextView(R.id.textview_text);
float[] widths = new float[LONG_TEXT.length()];
@@ -3176,6 +3753,8 @@
mTextView.setMaxLines(maxLines);
mTextView.requestLayout();
+ assertEquals(2, mTextView.getMaxLines());
+ assertEquals(-1, mTextView.getMaxHeight());
assertTrue(mTextView.getHeight() <= maxLines * mTextView.getLineHeight());
}
@@ -3269,17 +3848,20 @@
mTextView.setMaxLines(-1);
}
- public void testSetMinLines() {
+ public void testAccessMinLines() {
mTextView = findTextView(R.id.textview_text);
setWidth(mTextView.getWidth() >> 3);
- int originalHeight = mTextView.getHeight();
int originalLines = mTextView.getLineCount();
setMinLines(originalLines - 1);
assertTrue((originalLines - 1) * mTextView.getLineHeight() <= mTextView.getHeight());
+ assertEquals(originalLines - 1, mTextView.getMinLines());
+ assertEquals(-1, mTextView.getMinHeight());
setMinLines(originalLines + 1);
assertTrue((originalLines + 1) * mTextView.getLineHeight() <= mTextView.getHeight());
+ assertEquals(originalLines + 1, mTextView.getMinLines());
+ assertEquals(-1, mTextView.getMinHeight());
}
public void testSetLines() {
@@ -3519,6 +4101,8 @@
mTextView.getCurrentHintTextColor());
assertEquals(mActivity.getResources().getColor(R.drawable.blue),
mTextView.getLinkTextColors().getDefaultColor());
+ assertEquals(mActivity.getResources().getColor(R.drawable.yellow),
+ mTextView.getHighlightColor());
mTextView.setTextAppearance(R.style.TextAppearance_Colors);
assertEquals(mActivity.getResources().getColor(R.drawable.black),
@@ -3527,6 +4111,8 @@
mTextView.getCurrentHintTextColor());
assertEquals(mActivity.getResources().getColor(R.drawable.yellow),
mTextView.getLinkTextColors().getDefaultColor());
+ assertEquals(mActivity.getResources().getColor(R.drawable.red),
+ mTextView.getHighlightColor());
mTextView.setTextAppearance(R.style.TextAppearance_NotColors);
assertEquals(17f, mTextView.getTextSize(), 0.01f);
@@ -3676,7 +4262,11 @@
}
public void testMarquee() {
- final MockTextView textView = new MockTextView(mActivity);
+ // Both are pointing to the same object. This works around current limitation in CTS
+ // coverage report tool for properly reporting coverage of base class method calls.
+ final MockTextView mockTextView = new MockTextView(mActivity);
+ final TextView textView = mockTextView;
+
textView.setText(LONG_TEXT);
textView.setSingleLine();
textView.setEllipsize(TruncateAt.MARQUEE);
@@ -3688,11 +4278,7 @@
// make the fading to be shown
textView.setHorizontalFadingEdgeEnabled(true);
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- mActivity.setContentView(layout);
- }
- });
+ mActivity.runOnUiThread(() -> mActivity.setContentView(layout));
mInstrumentation.waitForIdleSync();
TestSelectedRunnable runnable = new TestSelectedRunnable(textView) {
@@ -3708,23 +4294,15 @@
// wait for the marquee to run
// fading is shown on both sides if the marquee runs for a while
- new PollingCheck(TIMEOUT) {
- @Override
- protected boolean check() {
- return textView.getLeftFadingEdgeStrength() > 0.0f
- && textView.getRightFadingEdgeStrength() > 0.0f;
- }
- }.run();
+ PollingCheck.waitFor(TIMEOUT, () -> mockTextView.getLeftFadingEdgeStrength() > 0.0f
+ && mockTextView.getRightFadingEdgeStrength() > 0.0f);
// wait for left marquee to fully apply
- new PollingCheck(TIMEOUT) {
- @Override
- protected boolean check() {
- return textView.getLeftFadingEdgeStrength() > 0.99f;
- }
- }.run();
+ PollingCheck.waitFor(TIMEOUT, () -> mockTextView.getLeftFadingEdgeStrength() > 0.99f);
+
assertFalse(runnable.getIsSelected1());
assertTrue(runnable.getIsSelected2());
+ assertEquals(-1, textView.getMarqueeRepeatLimit());
runnable = new TestSelectedRunnable(textView) {
public void run() {
@@ -3741,27 +4319,28 @@
mInstrumentation.waitForIdleSync();
assertTrue(runnable.getIsSelected1());
assertFalse(runnable.getIsSelected2());
- assertEquals(0.0f, textView.getLeftFadingEdgeStrength(), 0.01f);
- assertTrue(textView.getRightFadingEdgeStrength() > 0.0f);
+ assertEquals(0.0f, mockTextView.getLeftFadingEdgeStrength(), 0.01f);
+ assertTrue(mockTextView.getRightFadingEdgeStrength() > 0.0f);
+ assertEquals(0, textView.getMarqueeRepeatLimit());
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- textView.setGravity(Gravity.RIGHT);
- }
- });
+ mActivity.runOnUiThread(() -> textView.setGravity(Gravity.RIGHT));
mInstrumentation.waitForIdleSync();
- assertTrue(textView.getLeftFadingEdgeStrength() > 0.0f);
- assertEquals(0.0f, textView.getRightFadingEdgeStrength(), 0.01f);
+ assertTrue(mockTextView.getLeftFadingEdgeStrength() > 0.0f);
+ assertEquals(0.0f, mockTextView.getRightFadingEdgeStrength(), 0.01f);
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- textView.setGravity(Gravity.CENTER_HORIZONTAL);
- }
- });
+ mActivity.runOnUiThread(() -> textView.setGravity(Gravity.CENTER_HORIZONTAL));
mInstrumentation.waitForIdleSync();
// there is no left fading (Is it correct?)
- assertEquals(0.0f, textView.getLeftFadingEdgeStrength(), 0.01f);
- assertTrue(textView.getRightFadingEdgeStrength() > 0.0f);
+ assertEquals(0.0f, mockTextView.getLeftFadingEdgeStrength(), 0.01f);
+ assertTrue(mockTextView.getRightFadingEdgeStrength() > 0.0f);
+ }
+
+ @MediumTest
+ public void testGetMarqueeRepeatLimit() {
+ final TextView textView = new TextView(mActivity);
+
+ textView.setMarqueeRepeatLimit(10);
+ assertEquals(10, textView.getMarqueeRepeatLimit());
}
public void testOnKeyMultiple() {
@@ -3975,14 +4554,16 @@
public void testSetOnEditorActionListener() {
mTextView = findTextView(R.id.textview_text);
- MockOnEditorActionListener listener = new MockOnEditorActionListener();
- assertFalse(listener.isOnEditorActionCalled());
+ final TextView.OnEditorActionListener mockOnEditorActionListener =
+ mock(TextView.OnEditorActionListener.class);
+ verifyZeroInteractions(mockOnEditorActionListener);
- mTextView.setOnEditorActionListener(listener);
- assertFalse(listener.isOnEditorActionCalled());
+ mTextView.setOnEditorActionListener(mockOnEditorActionListener);
+ verifyZeroInteractions(mockOnEditorActionListener);
mTextView.onEditorAction(EditorInfo.IME_ACTION_DONE);
- assertTrue(listener.isOnEditorActionCalled());
+ verify(mockOnEditorActionListener, times(1)).onEditorAction(mTextView,
+ EditorInfo.IME_ACTION_DONE, null);
}
public void testAccessImeOptions() {
@@ -4151,19 +4732,78 @@
mInstrumentation.waitForIdleSync();
assertTrue(mTextView.isFocused());
- new PollingCheck() {
- @Override
- protected boolean check() {
- return mTextView.isInputMethodTarget();
- }
- }.run();
+ PollingCheck.waitFor(() -> mTextView.isInputMethodTarget());
}
- public void testBeginEndBatchEdit() {
- mTextView = findTextView(R.id.textview_text);
+ @MediumTest
+ public void testBeginEndBatchEditAreNotCalledForNonEditableText() {
+ final MockTextView mockTextView = new MockTextView(mActivity);
- mTextView.beginBatchEdit();
- mTextView.endBatchEdit();
+ assertFalse("TextView should not call onBeginBatchEdit during initialization",
+ mockTextView.hasCalledOnBeginBatchEdit());
+ assertFalse("TextView should not call onEndBatchEdit during initialization",
+ mockTextView.hasCalledOnEndBatchEdit());
+
+ // Since TextView doesn't support editing, the callbacks should not be called
+ mockTextView.beginBatchEdit();
+ assertFalse("Should not call onBeginBatchEdit when TextView doesn't support editing",
+ mockTextView.hasCalledOnBeginBatchEdit());
+ assertFalse("Should not call onEndBatchEdit when TextView doesn't support editing",
+ mockTextView.hasCalledOnEndBatchEdit());
+
+ mockTextView.endBatchEdit();
+ assertFalse("Should not call onBeginBatchEdit when TextView doesn't support editing",
+ mockTextView.hasCalledOnEndBatchEdit());
+ assertFalse("Should not call onEndBatchEdit when TextView doesn't support editing",
+ mockTextView.hasCalledOnEndBatchEdit());
+ }
+
+ @MediumTest
+ public void testBeginEndBatchEditCallbacksAreCalledForEditableText() {
+ final MockTextView mockTextView = new MockTextView(mActivity);
+
+ final FrameLayout layout = new FrameLayout(getActivity());
+ ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT);
+ layout.addView(mockTextView, layoutParams);
+ layout.setLayoutParams(layoutParams);
+
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ getActivity().setContentView(layout);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ mockTextView.setKeyListener(QwertyKeyListener.getInstance(false, Capitalize.NONE));
+ mockTextView.setText("", BufferType.EDITABLE);
+ mockTextView.requestFocus();
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ mockTextView.reset();
+ assertTrue(mockTextView.hasFocus());
+ assertFalse("onBeginBatchEdit should be false",
+ mockTextView.hasCalledOnBeginBatchEdit());
+ assertFalse("onEndBatchEdit should be false",
+ mockTextView.hasCalledOnEndBatchEdit());
+
+ mockTextView.beginBatchEdit();
+ assertTrue("onBeginBatchEdit should be called after beginBatchEdit",
+ mockTextView.hasCalledOnBeginBatchEdit());
+ assertFalse("onEndBatchEdit should not be called after beginBatchEdit",
+ mockTextView.hasCalledOnEndBatchEdit());
+
+ mockTextView.reset();
+ mockTextView.endBatchEdit();
+ assertFalse("onBeginBatchEdit should not be called after endBatchEdit",
+ mockTextView.hasCalledOnBeginBatchEdit());
+ assertTrue("onEndBatchEdit should be called after endBatchEdit",
+ mockTextView.hasCalledOnEndBatchEdit());
}
@UiThreadTest
@@ -4779,228 +5419,213 @@
assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getTextAlignment());
}
+ private void verifyCompoundDrawables(@NonNull TextView textView,
+ @IdRes int expectedLeftDrawableId, @IdRes int expectedRightDrawableId,
+ @IdRes int expectedTopDrawableId, @IdRes int expectedBottomDrawableId) {
+ final Drawable[] compoundDrawables = textView.getCompoundDrawables();
+ if (expectedLeftDrawableId < 0) {
+ assertNull(compoundDrawables[0]);
+ } else {
+ WidgetTestUtils.assertEquals(getBitmap(expectedLeftDrawableId),
+ ((BitmapDrawable) compoundDrawables[0]).getBitmap());
+ }
+ if (expectedTopDrawableId < 0) {
+ assertNull(compoundDrawables[1]);
+ } else {
+ WidgetTestUtils.assertEquals(getBitmap(expectedTopDrawableId),
+ ((BitmapDrawable) compoundDrawables[1]).getBitmap());
+ }
+ if (expectedRightDrawableId < 0) {
+ assertNull(compoundDrawables[2]);
+ } else {
+ WidgetTestUtils.assertEquals(getBitmap(expectedRightDrawableId),
+ ((BitmapDrawable) compoundDrawables[2]).getBitmap());
+ }
+ if (expectedBottomDrawableId < 0) {
+ assertNull(compoundDrawables[3]);
+ } else {
+ WidgetTestUtils.assertEquals(getBitmap(expectedBottomDrawableId),
+ ((BitmapDrawable) compoundDrawables[3]).getBitmap());
+ }
+ }
+
+ private void verifyCompoundDrawablesRelative(@NonNull TextView textView,
+ @IdRes int expectedStartDrawableId, @IdRes int expectedEndDrawableId,
+ @IdRes int expectedTopDrawableId, @IdRes int expectedBottomDrawableId) {
+ final Drawable[] compoundDrawablesRelative = textView.getCompoundDrawablesRelative();
+ if (expectedStartDrawableId < 0) {
+ assertNull(compoundDrawablesRelative[0]);
+ } else {
+ WidgetTestUtils.assertEquals(getBitmap(expectedStartDrawableId),
+ ((BitmapDrawable) compoundDrawablesRelative[0]).getBitmap());
+ }
+ if (expectedTopDrawableId < 0) {
+ assertNull(compoundDrawablesRelative[1]);
+ } else {
+ WidgetTestUtils.assertEquals(getBitmap(expectedTopDrawableId),
+ ((BitmapDrawable) compoundDrawablesRelative[1]).getBitmap());
+ }
+ if (expectedEndDrawableId < 0) {
+ assertNull(compoundDrawablesRelative[2]);
+ } else {
+ WidgetTestUtils.assertEquals(getBitmap(expectedEndDrawableId),
+ ((BitmapDrawable) compoundDrawablesRelative[2]).getBitmap());
+ }
+ if (expectedBottomDrawableId < 0) {
+ assertNull(compoundDrawablesRelative[3]);
+ } else {
+ WidgetTestUtils.assertEquals(getBitmap(expectedBottomDrawableId),
+ ((BitmapDrawable) compoundDrawablesRelative[3]).getBitmap());
+ }
+ }
+
@UiThreadTest
public void testDrawableResolution() {
- final int LEFT = 0;
- final int TOP = 1;
- final int RIGHT = 2;
- final int BOTTOM = 3;
-
- TextViewCtsActivity activity = getActivity();
-
// Case 1.1: left / right drawable defined in default LTR mode
- TextView tv = (TextView) activity.findViewById(R.id.textview_drawable_1_1);
- Drawable[] drawables = tv.getCompoundDrawables();
-
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
- ((BitmapDrawable) drawables[LEFT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
- ((BitmapDrawable) drawables[RIGHT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
- ((BitmapDrawable) drawables[TOP]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
- ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+ TextView tv = (TextView) mActivity.findViewById(R.id.textview_drawable_1_1);
+ verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
+ R.drawable.icon_green, R.drawable.icon_yellow);
+ verifyCompoundDrawablesRelative(tv, -1, -1,
+ R.drawable.icon_green, R.drawable.icon_yellow);
// Case 1.2: left / right drawable defined in default RTL mode
- tv = (TextView) activity.findViewById(R.id.textview_drawable_1_2);
- drawables = tv.getCompoundDrawables();
-
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
- ((BitmapDrawable) drawables[LEFT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
- ((BitmapDrawable) drawables[RIGHT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
- ((BitmapDrawable) drawables[TOP]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
- ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+ tv = (TextView) mActivity.findViewById(R.id.textview_drawable_1_2);
+ verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
+ R.drawable.icon_green, R.drawable.icon_yellow);
+ verifyCompoundDrawablesRelative(tv, -1, -1,
+ R.drawable.icon_green, R.drawable.icon_yellow);
// Case 2.1: start / end drawable defined in LTR mode
- tv = (TextView) activity.findViewById(R.id.textview_drawable_2_1);
- drawables = tv.getCompoundDrawables();
-
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
- ((BitmapDrawable) drawables[LEFT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
- ((BitmapDrawable) drawables[RIGHT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
- ((BitmapDrawable) drawables[TOP]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
- ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+ tv = (TextView) mActivity.findViewById(R.id.textview_drawable_2_1);
+ verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
+ R.drawable.icon_green, R.drawable.icon_yellow);
+ verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
+ R.drawable.icon_green, R.drawable.icon_yellow);
// Case 2.2: start / end drawable defined in RTL mode
- tv = (TextView) activity.findViewById(R.id.textview_drawable_2_2);
- drawables = tv.getCompoundDrawables();
-
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
- ((BitmapDrawable) drawables[LEFT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
- ((BitmapDrawable) drawables[RIGHT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
- ((BitmapDrawable) drawables[TOP]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
- ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+ tv = (TextView) mActivity.findViewById(R.id.textview_drawable_2_2);
+ verifyCompoundDrawables(tv, R.drawable.icon_red, R.drawable.icon_blue,
+ R.drawable.icon_green, R.drawable.icon_yellow);
+ verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
+ R.drawable.icon_green, R.drawable.icon_yellow);
// Case 3.1: left / right / start / end drawable defined in LTR mode
- tv = (TextView) activity.findViewById(R.id.textview_drawable_3_1);
- drawables = tv.getCompoundDrawables();
-
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
- ((BitmapDrawable) drawables[LEFT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
- ((BitmapDrawable) drawables[RIGHT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
- ((BitmapDrawable) drawables[TOP]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
- ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+ tv = (TextView) mActivity.findViewById(R.id.textview_drawable_3_1);
+ verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
+ R.drawable.icon_green, R.drawable.icon_yellow);
+ verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
+ R.drawable.icon_green, R.drawable.icon_yellow);
// Case 3.2: left / right / start / end drawable defined in RTL mode
- tv = (TextView) activity.findViewById(R.id.textview_drawable_3_2);
- drawables = tv.getCompoundDrawables();
-
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
- ((BitmapDrawable) drawables[LEFT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
- ((BitmapDrawable) drawables[RIGHT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
- ((BitmapDrawable) drawables[TOP]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
- ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+ tv = (TextView) mActivity.findViewById(R.id.textview_drawable_3_2);
+ verifyCompoundDrawables(tv, R.drawable.icon_red, R.drawable.icon_blue,
+ R.drawable.icon_green, R.drawable.icon_yellow);
+ verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
+ R.drawable.icon_green, R.drawable.icon_yellow);
// Case 4.1: start / end drawable defined in LTR mode inside a layout
// that defines the layout direction
- tv = (TextView) activity.findViewById(R.id.textview_drawable_4_1);
- drawables = tv.getCompoundDrawables();
-
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
- ((BitmapDrawable) drawables[LEFT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
- ((BitmapDrawable) drawables[RIGHT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
- ((BitmapDrawable) drawables[TOP]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
- ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+ tv = (TextView) mActivity.findViewById(R.id.textview_drawable_4_1);
+ verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
+ R.drawable.icon_green, R.drawable.icon_yellow);
+ verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
+ R.drawable.icon_green, R.drawable.icon_yellow);
// Case 4.2: start / end drawable defined in RTL mode inside a layout
// that defines the layout direction
- tv = (TextView) activity.findViewById(R.id.textview_drawable_4_2);
- drawables = tv.getCompoundDrawables();
-
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
- ((BitmapDrawable) drawables[LEFT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
- ((BitmapDrawable) drawables[RIGHT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
- ((BitmapDrawable) drawables[TOP]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
- ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+ tv = (TextView) mActivity.findViewById(R.id.textview_drawable_4_2);
+ verifyCompoundDrawables(tv, R.drawable.icon_red, R.drawable.icon_blue,
+ R.drawable.icon_green, R.drawable.icon_yellow);
+ verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
+ R.drawable.icon_green, R.drawable.icon_yellow);
// Case 5.1: left / right / start / end drawable defined in LTR mode inside a layout
// that defines the layout direction
- tv = (TextView) activity.findViewById(R.id.textview_drawable_3_1);
- drawables = tv.getCompoundDrawables();
-
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
- ((BitmapDrawable) drawables[LEFT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
- ((BitmapDrawable) drawables[RIGHT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
- ((BitmapDrawable) drawables[TOP]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
- ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+ tv = (TextView) mActivity.findViewById(R.id.textview_drawable_5_1);
+ verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
+ R.drawable.icon_green, R.drawable.icon_yellow);
+ verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
+ R.drawable.icon_green, R.drawable.icon_yellow);
// Case 5.2: left / right / start / end drawable defined in RTL mode inside a layout
// that defines the layout direction
- tv = (TextView) activity.findViewById(R.id.textview_drawable_3_2);
- drawables = tv.getCompoundDrawables();
-
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
- ((BitmapDrawable) drawables[LEFT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
- ((BitmapDrawable) drawables[RIGHT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
- ((BitmapDrawable) drawables[TOP]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
- ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+ tv = (TextView) mActivity.findViewById(R.id.textview_drawable_5_2);
+ verifyCompoundDrawables(tv, R.drawable.icon_red, R.drawable.icon_blue,
+ R.drawable.icon_green, R.drawable.icon_yellow);
+ verifyCompoundDrawablesRelative(tv, R.drawable.icon_blue, R.drawable.icon_red,
+ R.drawable.icon_green, R.drawable.icon_yellow);
}
@UiThreadTest
public void testDrawableResolution2() {
- final int LEFT = 0;
- final int TOP = 1;
- final int RIGHT = 2;
- final int BOTTOM = 3;
-
- TextViewCtsActivity activity = getActivity();
-
// Case 1.1: left / right drawable defined in default LTR mode
- TextView tv = (TextView) activity.findViewById(R.id.textview_drawable_1_1);
- Drawable[] drawables = tv.getCompoundDrawables();
-
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
- ((BitmapDrawable) drawables[LEFT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
- ((BitmapDrawable) drawables[RIGHT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
- ((BitmapDrawable) drawables[TOP]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
- ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+ TextView tv = (TextView) mActivity.findViewById(R.id.textview_drawable_1_1);
+ verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
+ R.drawable.icon_green, R.drawable.icon_yellow);
tv.setCompoundDrawables(null, null, getDrawable(R.drawable.icon_yellow), null);
- drawables = tv.getCompoundDrawables();
+ verifyCompoundDrawables(tv, -1, R.drawable.icon_yellow, -1, -1);
- assertNull(drawables[LEFT]);
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
- ((BitmapDrawable) drawables[RIGHT]).getBitmap());
- assertNull(drawables[TOP]);
- assertNull(drawables[BOTTOM]);
-
- tv = (TextView) activity.findViewById(R.id.textview_drawable_1_2);
- drawables = tv.getCompoundDrawables();
-
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
- ((BitmapDrawable) drawables[LEFT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
- ((BitmapDrawable) drawables[RIGHT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_green),
- ((BitmapDrawable) drawables[TOP]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
- ((BitmapDrawable) drawables[BOTTOM]).getBitmap());
+ tv = (TextView) mActivity.findViewById(R.id.textview_drawable_1_2);
+ verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red,
+ R.drawable.icon_green, R.drawable.icon_yellow);
tv.setCompoundDrawables(getDrawable(R.drawable.icon_yellow), null, null, null);
- drawables = tv.getCompoundDrawables();
+ verifyCompoundDrawables(tv, R.drawable.icon_yellow, -1, -1, -1);
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
- ((BitmapDrawable) drawables[LEFT]).getBitmap());
- assertNull(drawables[RIGHT]);
- assertNull(drawables[TOP]);
- assertNull(drawables[BOTTOM]);
+ tv = (TextView) mActivity.findViewById(R.id.textview_ltr);
+ verifyCompoundDrawables(tv, -1, -1, -1, -1);
- tv = (TextView) activity.findViewById(R.id.textview_ltr);
- drawables = tv.getCompoundDrawables();
-
- assertNull(drawables[LEFT]);
- assertNull(drawables[RIGHT]);
- assertNull(drawables[TOP]);
- assertNull(drawables[BOTTOM]);
-
- tv.setCompoundDrawables(getDrawable(R.drawable.icon_blue), null, getDrawable(R.drawable.icon_red), null);
- drawables = tv.getCompoundDrawables();
-
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_blue),
- ((BitmapDrawable) drawables[LEFT]).getBitmap());
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_red),
- ((BitmapDrawable) drawables[RIGHT]).getBitmap());
- assertNull(drawables[TOP]);
- assertNull(drawables[BOTTOM]);
+ tv.setCompoundDrawables(getDrawable(R.drawable.icon_blue), null,
+ getDrawable(R.drawable.icon_red), null);
+ verifyCompoundDrawables(tv, R.drawable.icon_blue, R.drawable.icon_red, -1, -1);
tv.setCompoundDrawablesRelative(getDrawable(R.drawable.icon_yellow), null, null, null);
- drawables = tv.getCompoundDrawables();
+ verifyCompoundDrawables(tv, R.drawable.icon_yellow, -1, -1, -1);
+ }
- WidgetTestUtils.assertEquals(getBitmap(R.drawable.icon_yellow),
- ((BitmapDrawable) drawables[LEFT]).getBitmap());
- assertNull(drawables[RIGHT]);
- assertNull(drawables[TOP]);
- assertNull(drawables[BOTTOM]);
+ public void testCompoundAndTotalPadding() {
+ final Resources res = mActivity.getResources();
+ final int drawablePadding = res.getDimensionPixelSize(R.dimen.textview_drawable_padding);
+ final int paddingLeft = res.getDimensionPixelSize(R.dimen.textview_padding_left);
+ final int paddingRight = res.getDimensionPixelSize(R.dimen.textview_padding_right);
+ final int paddingTop = res.getDimensionPixelSize(R.dimen.textview_padding_top);
+ final int paddingBottom = res.getDimensionPixelSize(R.dimen.textview_padding_bottom);
+ final int iconSize = TestUtils.dpToPx(mActivity, 32);
+
+ final TextView textViewLtr = (TextView) mActivity.findViewById(
+ R.id.textview_compound_drawable_ltr);
+ final int combinedPaddingLeftLtr = paddingLeft + drawablePadding + iconSize;
+ final int combinedPaddingRightLtr = paddingRight + drawablePadding + iconSize;
+ assertEquals(combinedPaddingLeftLtr, textViewLtr.getCompoundPaddingLeft());
+ assertEquals(combinedPaddingLeftLtr, textViewLtr.getCompoundPaddingStart());
+ assertEquals(combinedPaddingLeftLtr, textViewLtr.getTotalPaddingLeft());
+ assertEquals(combinedPaddingLeftLtr, textViewLtr.getTotalPaddingStart());
+ assertEquals(combinedPaddingRightLtr, textViewLtr.getCompoundPaddingRight());
+ assertEquals(combinedPaddingRightLtr, textViewLtr.getCompoundPaddingEnd());
+ assertEquals(combinedPaddingRightLtr, textViewLtr.getTotalPaddingRight());
+ assertEquals(combinedPaddingRightLtr, textViewLtr.getTotalPaddingEnd());
+ assertEquals(paddingTop + drawablePadding + iconSize,
+ textViewLtr.getCompoundPaddingTop());
+ assertEquals(paddingBottom + drawablePadding + iconSize,
+ textViewLtr.getCompoundPaddingBottom());
+
+ final TextView textViewRtl = (TextView) mActivity.findViewById(
+ R.id.textview_compound_drawable_rtl);
+ final int combinedPaddingLeftRtl = paddingLeft + drawablePadding + iconSize;
+ final int combinedPaddingRightRtl = paddingRight + drawablePadding + iconSize;
+ assertEquals(combinedPaddingLeftRtl, textViewRtl.getCompoundPaddingLeft());
+ assertEquals(combinedPaddingLeftRtl, textViewRtl.getCompoundPaddingEnd());
+ assertEquals(combinedPaddingLeftRtl, textViewRtl.getTotalPaddingLeft());
+ assertEquals(combinedPaddingLeftRtl, textViewRtl.getTotalPaddingEnd());
+ assertEquals(combinedPaddingRightRtl, textViewRtl.getCompoundPaddingRight());
+ assertEquals(combinedPaddingRightRtl, textViewRtl.getCompoundPaddingStart());
+ assertEquals(combinedPaddingRightRtl, textViewRtl.getTotalPaddingRight());
+ assertEquals(combinedPaddingRightRtl, textViewRtl.getTotalPaddingStart());
+ assertEquals(paddingTop + drawablePadding + iconSize,
+ textViewRtl.getCompoundPaddingTop());
+ assertEquals(paddingBottom + drawablePadding + iconSize,
+ textViewRtl.getCompoundPaddingBottom());
}
public void testSetGetBreakStrategy() {
@@ -5076,9 +5701,11 @@
// Check default value.
assertNull(mTextView.getCustomSelectionActionModeCallback());
- MockActionModeCallback callbackBlockActionMode = new MockActionModeCallback(false);
- mTextView.setCustomSelectionActionModeCallback(callbackBlockActionMode);
- assertEquals(callbackBlockActionMode,
+ final ActionMode.Callback mockActionModeCallback = mock(ActionMode.Callback.class);
+ when(mockActionModeCallback.onCreateActionMode(any(ActionMode.class), any(Menu.class))).
+ thenReturn(Boolean.FALSE);
+ mTextView.setCustomSelectionActionModeCallback(mockActionModeCallback);
+ assertEquals(mockActionModeCallback,
mTextView.getCustomSelectionActionModeCallback());
mActivity.runOnUiThread(new Runnable() {
@@ -5093,7 +5720,8 @@
});
mInstrumentation.waitForIdleSync();
- assertEquals(1, callbackBlockActionMode.getCreateCount());
+ verify(mockActionModeCallback, times(1)).onCreateActionMode(
+ any(ActionMode.class), any(Menu.class));
mActivity.runOnUiThread(new Runnable() {
public void run() {
@@ -5104,12 +5732,13 @@
mInstrumentation.waitForIdleSync();
// Action mode was blocked.
- assertEquals(0, callbackBlockActionMode.getDestroyCount());
+ verify(mockActionModeCallback, never()).onDestroyActionMode(any(ActionMode.class));
- // Overwrite callback.
- MockActionModeCallback callbackStartActionMode = new MockActionModeCallback(true);
- mTextView.setCustomSelectionActionModeCallback(callbackStartActionMode);
- assertEquals(callbackStartActionMode, mTextView.getCustomSelectionActionModeCallback());
+ // Reset and reconfigure callback.
+ reset(mockActionModeCallback);
+ when(mockActionModeCallback.onCreateActionMode(any(ActionMode.class), any(Menu.class))).
+ thenReturn(Boolean.TRUE);
+ assertEquals(mockActionModeCallback, mTextView.getCustomSelectionActionModeCallback());
mActivity.runOnUiThread(new Runnable() {
public void run() {
@@ -5124,7 +5753,8 @@
});
mInstrumentation.waitForIdleSync();
- assertEquals(1, callbackStartActionMode.getCreateCount());
+ verify(mockActionModeCallback, times(1)).onCreateActionMode(
+ any(ActionMode.class), any(Menu.class));
mActivity.runOnUiThread(new Runnable() {
public void run() {
@@ -5135,70 +5765,317 @@
mInstrumentation.waitForIdleSync();
// Action mode was started
- assertEquals(1, callbackStartActionMode.getDestroyCount());
+ verify(mockActionModeCallback, times(1)).onDestroyActionMode(any(ActionMode.class));
}
- public void testSetAndGetCustomInseltionActionMode() {
+ public void testSetAndGetCustomInsertionActionMode() {
initTextViewForTyping();
// Check default value.
assertNull(mTextView.getCustomInsertionActionModeCallback());
- MockActionModeCallback callback = new MockActionModeCallback(false);
- mTextView.setCustomInsertionActionModeCallback(callback);
- assertEquals(callback, mTextView.getCustomInsertionActionModeCallback());
+ final ActionMode.Callback mockActionModeCallback = mock(ActionMode.Callback.class);
+ when(mockActionModeCallback.onCreateActionMode(any(ActionMode.class), any(Menu.class))).
+ thenReturn(Boolean.FALSE);
+ mTextView.setCustomInsertionActionModeCallback(mockActionModeCallback);
+ assertEquals(mockActionModeCallback, mTextView.getCustomInsertionActionModeCallback());
// TODO(Bug: 22033189): Tests the set callback is actually used.
}
- private static class MockActionModeCallback implements ActionMode.Callback {
- private int mCreateCount = 0;
- private int mDestroyCount = 0;
- private final boolean mAllowToStartActionMode;
+ public void testTextShadows() {
+ final TextView textViewWithConfiguredShadow =
+ (TextView) mActivity.findViewById(R.id.textview_with_shadow);
+ assertEquals(1.0f, textViewWithConfiguredShadow.getShadowDx());
+ assertEquals(2.0f, textViewWithConfiguredShadow.getShadowDy());
+ assertEquals(3.0f, textViewWithConfiguredShadow.getShadowRadius());
+ assertEquals(Color.GREEN, textViewWithConfiguredShadow.getShadowColor());
- public MockActionModeCallback(boolean allowToStartActionMode) {
- mAllowToStartActionMode = allowToStartActionMode;
- }
+ final TextView textView = (TextView) mActivity.findViewById(R.id.textview_text);
+ assertEquals(0.0f, textView.getShadowDx());
+ assertEquals(0.0f, textView.getShadowDy());
+ assertEquals(0.0f, textView.getShadowRadius());
- public int getCreateCount() {
- return mCreateCount;
- }
+ mActivity.runOnUiThread(() -> textView.setShadowLayer(5.0f, 3.0f, 4.0f, Color.RED));
+ mInstrumentation.waitForIdleSync();
+ assertEquals(3.0f, textView.getShadowDx());
+ assertEquals(4.0f, textView.getShadowDy());
+ assertEquals(5.0f, textView.getShadowRadius());
+ assertEquals(Color.RED, textView.getShadowColor());
+ }
- public int getDestroyCount() {
- return mDestroyCount;
+ public void testFontFeatureSettings() {
+ final TextView textView = (TextView) mActivity.findViewById(R.id.textview_text);
+ assertTrue(TextUtils.isEmpty(textView.getFontFeatureSettings()));
+
+ mActivity.runOnUiThread(() -> textView.setFontFeatureSettings("smcp"));
+ mInstrumentation.waitForIdleSync();
+ assertEquals("smcp", textView.getFontFeatureSettings());
+
+ mActivity.runOnUiThread(() -> textView.setFontFeatureSettings("frac"));
+ mInstrumentation.waitForIdleSync();
+ assertEquals("frac", textView.getFontFeatureSettings());
+ }
+
+ private static class SoftInputResultReceiver extends ResultReceiver {
+ private boolean mIsDone;
+ private int mResultCode;
+
+ public SoftInputResultReceiver(Handler handler) {
+ super(handler);
}
@Override
- public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
- return false;
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ mResultCode = resultCode;
+ mIsDone = true;
}
- @Override
- public void onDestroyActionMode(ActionMode mode) {
- mDestroyCount++;
+ public void reset() {
+ mIsDone = false;
+ }
+ }
+
+ public void testAccessShowSoftInputOnFocus() {
+ if (!mActivity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_INPUT_METHODS)) {
+ return;
}
- @Override
- public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- mCreateCount++;
- return mAllowToStartActionMode;
+ // Scroll down to our EditText
+ final ScrollView scrollView = (ScrollView) mActivity.findViewById(R.id.scroller);
+ mTextView = findTextView(R.id.editview_text);
+ mActivity.runOnUiThread(() -> scrollView.fullScroll(View.FOCUS_DOWN));
+ mInstrumentation.waitForIdleSync();
+
+ // Mark it to show soft input on focus
+ mActivity.runOnUiThread(() -> mTextView.setShowSoftInputOnFocus(true));
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mTextView.getShowSoftInputOnFocus());
+
+ // And emulate click on it
+ TouchUtils.clickView(this, mTextView);
+
+ // Verify that input method manager is active and accepting text
+ final InputMethodManager imManager = (InputMethodManager) mActivity
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+ PollingCheck.waitFor(() -> imManager.isActive());
+ assertTrue(imManager.isAcceptingText());
+ assertTrue(imManager.isActive(mTextView));
+
+ // Since there is no API to check that soft input is showing, we're going to ask
+ // the input method manager to show soft input, passing our custom result receiver.
+ // We're expecting to get UNCHANGED_SHOWN, indicating that the soft input was already
+ // showing before showSoftInput was called.
+ SoftInputResultReceiver receiver = new SoftInputResultReceiver(mHandler);
+ imManager.showSoftInput(mTextView, 0, receiver);
+ PollingCheck.waitFor(() -> receiver.mIsDone);
+ assertEquals(InputMethodManager.RESULT_UNCHANGED_SHOWN, receiver.mResultCode);
+
+ // Close soft input
+ sendKeys(KeyEvent.KEYCODE_BACK);
+
+ // Reconfigure our edit text to not show soft input on focus
+ mActivity.runOnUiThread(() -> mTextView.setShowSoftInputOnFocus(false));
+ mInstrumentation.waitForIdleSync();
+ assertFalse(mTextView.getShowSoftInputOnFocus());
+
+ // Emulate click on it
+ TouchUtils.clickView(this, mTextView);
+
+ // Ask input method manager to show soft input again. This time we're expecting to get
+ // SHOWN, indicating that the soft input was not showing before showSoftInput was called.
+ receiver.reset();
+ imManager.showSoftInput(mTextView, 0, receiver);
+ PollingCheck.waitFor(() -> receiver.mIsDone);
+ assertEquals(InputMethodManager.RESULT_SHOWN, receiver.mResultCode);
+
+ // Close soft input
+ sendKeys(KeyEvent.KEYCODE_BACK);
+ }
+
+ public void testIsSuggestionsEnabled() {
+ mTextView = findTextView(R.id.textview_text);
+
+ // Anything without InputType.TYPE_CLASS_TEXT doesn't have suggestions enabled
+ mInstrumentation.runOnMainSync(() -> mTextView.setInputType(InputType.TYPE_CLASS_DATETIME));
+ assertFalse(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(() -> mTextView.setInputType(InputType.TYPE_CLASS_PHONE));
+ assertFalse(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(() -> mTextView.setInputType(InputType.TYPE_CLASS_NUMBER));
+ assertFalse(mTextView.isSuggestionsEnabled());
+
+ // From this point our text view has InputType.TYPE_CLASS_TEXT
+
+ // Anything with InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS doesn't have suggestions enabled
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS));
+ assertFalse(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL |
+ InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS));
+ assertFalse(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS |
+ InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS));
+ assertFalse(mTextView.isSuggestionsEnabled());
+
+ // Otherwise suggestions are enabled for specific type variations enumerated in the
+ // documentation of TextView.isSuggestionsEnabled
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL));
+ assertTrue(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT));
+ assertTrue(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE));
+ assertTrue(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE));
+ assertTrue(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT));
+ assertTrue(mTextView.isSuggestionsEnabled());
+
+ // and not on any other type variation
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS));
+ assertFalse(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_FILTER));
+ assertFalse(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD));
+ assertFalse(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PERSON_NAME));
+ assertFalse(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PHONETIC));
+ assertFalse(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS));
+ assertFalse(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI));
+ assertFalse(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT |
+ InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD));
+ assertFalse(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT |
+ InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS));
+ assertFalse(mTextView.isSuggestionsEnabled());
+
+ mInstrumentation.runOnMainSync(
+ () -> mTextView.setInputType(
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD));
+ assertFalse(mTextView.isSuggestionsEnabled());
+ }
+
+ public void testAccessLetterSpacing() {
+ mTextView = findTextView(R.id.textview_text);
+ assertEquals(0.0f, mTextView.getLetterSpacing());
+
+ final CharSequence text = mTextView.getText();
+ final int textLength = text.length();
+
+ // Get advance widths of each character at the default letter spacing
+ final float[] initialWidths = new float[textLength];
+ mTextView.getPaint().getTextWidths(text.toString(), initialWidths);
+
+ // Get advance widths of each character at letter spacing = 1.0f
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mTextView,
+ () -> mTextView.setLetterSpacing(1.0f));
+ assertEquals(1.0f, mTextView.getLetterSpacing());
+ final float[] singleWidths = new float[textLength];
+ mTextView.getPaint().getTextWidths(text.toString(), singleWidths);
+
+ // Get advance widths of each character at letter spacing = 2.0f
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mTextView,
+ () -> mTextView.setLetterSpacing(2.0f));
+ assertEquals(2.0f, mTextView.getLetterSpacing());
+ final float[] doubleWidths = new float[textLength];
+ mTextView.getPaint().getTextWidths(text.toString(), doubleWidths);
+
+ // Since letter spacing setter treats the parameter as EM units, and we don't have
+ // a way to convert EMs into pixels, go over the three arrays of advance widths and
+ // test that the extra advance width at letter spacing 2.0f is double the extra
+ // advance width at letter spacing 1.0f.
+ for (int i = 0; i < textLength; i++) {
+ float singleWidthDelta = singleWidths[i] - initialWidths[i];
+ float doubleWidthDelta = doubleWidths[i] - initialWidths[i];
+ assertEquals("At index " + i + " initial is " + initialWidths[i] +
+ ", single is " + singleWidths[i] + " and double is " + doubleWidths[i],
+ singleWidthDelta * 2.0f, doubleWidthDelta, 0.05f);
+ }
+ }
+
+ private void verifyGetOffsetForPosition(final int x, final int y) {
+ final int actual = mTextView.getOffsetForPosition(x, y);
+
+ final Layout layout = mTextView.getLayout();
+ if (layout == null) {
+ assertEquals("For [" + x + ", " + y + "]", -1, actual);
+ return;
}
- @Override
- public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- return false;
- }
- };
+ // Get the line which corresponds to the Y position
+ final int line = layout.getLineForVertical(y + mTextView.getScrollY());
+ // Get the offset in that line that corresponds to the X position
+ final int expected = layout.getOffsetForHorizontal(line, x + mTextView.getScrollX());
+ assertEquals("For [" + x + ", " + y + "]", expected, actual);
+ }
- private static class MockOnEditorActionListener implements OnEditorActionListener {
- private boolean isOnEditorActionCalled;
+ public void testGetOffsetForPosition() {
+ mTextView = findTextView(R.id.textview_text);
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mTextView, () -> {
+ mTextView.setText(LONG_TEXT);
+ mTextView.setPadding(0, 0, 0, 0);
+ });
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- isOnEditorActionCalled = true;
- return true;
- }
+ assertNotNull(mTextView.getLayout());
+ final int viewWidth = mTextView.getWidth();
+ final int viewHeight = mTextView.getHeight();
+ final int lineHeight = mTextView.getLineHeight();
- public boolean isOnEditorActionCalled() {
- return isOnEditorActionCalled;
- }
+ verifyGetOffsetForPosition(0, 0);
+ verifyGetOffsetForPosition(0, viewHeight / 2);
+ verifyGetOffsetForPosition(viewWidth / 3, lineHeight / 2);
+ verifyGetOffsetForPosition(viewWidth / 2, viewHeight / 2);
+ verifyGetOffsetForPosition(viewWidth, viewHeight);
}
private void layout(final TextView textView) {
@@ -5235,6 +6112,15 @@
return mActivity.getResources().getDrawable(resid);
}
+ private void setMaxLines(final int lines) {
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ mTextView.setMaxLines(lines);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ }
+
private void setMaxWidth(final int pixels) {
mActivity.runOnUiThread(new Runnable() {
public void run() {
@@ -5411,56 +6297,6 @@
}
}
- private class MockEditableFactory extends Editable.Factory {
- private boolean mhasCalledNewEditable;
- private CharSequence mSource;
-
- public boolean hasCalledNewEditable() {
- return mhasCalledNewEditable;
- }
-
- public void reset() {
- mhasCalledNewEditable = false;
- mSource = null;
- }
-
- public CharSequence getSource() {
- return mSource;
- }
-
- @Override
- public Editable newEditable(CharSequence source) {
- mhasCalledNewEditable = true;
- mSource = source;
- return super.newEditable(source);
- }
- }
-
- private class MockSpannableFactory extends Spannable.Factory {
- private boolean mHasCalledNewSpannable;
- private CharSequence mSource;
-
- public boolean hasCalledNewSpannable() {
- return mHasCalledNewSpannable;
- }
-
- public void reset() {
- mHasCalledNewSpannable = false;
- mSource = null;
- }
-
- public CharSequence getSource() {
- return mSource;
- }
-
- @Override
- public Spannable newSpannable(CharSequence source) {
- mHasCalledNewSpannable = true;
- mSource = source;
- return super.newSpannable(source);
- }
- }
-
private static class MockTextWatcher implements TextWatcher {
private boolean mHasCalledAfterTextChanged;
private boolean mHasCalledBeforeTextChanged;
@@ -5498,70 +6334,6 @@
}
/**
- * The listener interface for receiving mockOnLongClick events. The class
- * that is interested in processing a mockOnLongClick event implements this
- * interface, and the object created with that class is registered with a
- * component using the component's
- * <code>addMockOnLongClickListener<code> method. When
- * the mockOnLongClick event occurs, that object's appropriate
- * method is invoked.
- *
- * @see MockOnLongClickEvent
- */
- private static class MockOnLongClickListener implements OnLongClickListener {
- private boolean mExpectedOnLongClickResult;
- private boolean mHasLongClicked;
-
- MockOnLongClickListener(boolean result) {
- mExpectedOnLongClickResult = result;
- }
-
- public boolean hasLongClicked() {
- return mHasLongClicked;
- }
-
- public boolean onLongClick(View v) {
- mHasLongClicked = true;
- return mExpectedOnLongClickResult;
- }
- }
-
- /**
- * The listener interface for receiving mockOnCreateContextMenu events. The
- * class that is interested in processing a mockOnCreateContextMenu event
- * implements this interface, and the object created with that class is
- * registered with a component using the component's
- * <code>addMockOnCreateContextMenuListener<code> method. When the
- * mockOnCreateContextMenu event occurs, that object's appropriate method is
- * invoked.
- *
- * @see MockOnCreateContextMenuEvent
- */
- private static class MockOnCreateContextMenuListener implements OnCreateContextMenuListener {
- private boolean mIsMenuItemsBlank;
- private boolean mHasCreatedContextMenu;
-
- MockOnCreateContextMenuListener(boolean isBlank) {
- this.mIsMenuItemsBlank = isBlank;
- }
-
- public boolean hasCreatedContextMenu() {
- return mHasCreatedContextMenu;
- }
-
- public void reset() {
- mHasCreatedContextMenu = false;
- }
-
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
- mHasCreatedContextMenu = true;
- if (!mIsMenuItemsBlank) {
- menu.add("menu item");
- }
- }
- }
-
- /**
* A TextWatcher that converts the text to spaces whenever the text changes.
*/
private static class ConvertToSpacesTextWatcher implements TextWatcher {
diff --git a/tests/tests/widget/src/android/widget/cts/TimePickerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/TimePickerCtsActivity.java
new file mode 100644
index 0000000..34fb8c0
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/TimePickerCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TimePicker;
+
+/**
+ * A minimal application for {@link TimePicker} test.
+ */
+public class TimePickerCtsActivity extends Activity {
+ /**
+ * Called when the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.timepicker);
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/TimePickerTest.java b/tests/tests/widget/src/android/widget/cts/TimePickerTest.java
index 39554bb..6dad194 100644
--- a/tests/tests/widget/src/android/widget/cts/TimePickerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TimePickerTest.java
@@ -16,46 +16,46 @@
package android.widget.cts;
-
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.os.Parcelable;
import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.SmallTest;
import android.util.AttributeSet;
import android.widget.TimePicker;
-import android.widget.TimePicker.OnTimeChangedListener;
+
+import static org.mockito.Mockito.*;
/**
* Test {@link TimePicker}.
*/
-public class TimePickerTest extends ActivityInstrumentationTestCase2<CtsActivity> {
+@SmallTest
+public class TimePickerTest extends ActivityInstrumentationTestCase2<TimePickerCtsActivity> {
private TimePicker mTimePicker;
-
private Activity mActivity;
-
- private Context mContext;
-
private Instrumentation mInstrumentation;
public TimePickerTest() {
- super("android.widget.cts", CtsActivity.class);
+ super("android.widget.cts", TimePickerCtsActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
+
mInstrumentation = getInstrumentation();
- mContext = mInstrumentation.getTargetContext();
mActivity = getActivity();
+ mTimePicker = (TimePicker) mActivity.findViewById(R.id.timepicker);
}
public void testConstructors() {
AttributeSet attrs =
- mContext.getResources().getLayout(android.widget.cts.R.layout.timepicker);
+ mActivity.getResources().getLayout(android.widget.cts.R.layout.timepicker);
assertNotNull(attrs);
- new TimePicker(mContext);
+ new TimePicker(mActivity);
try {
new TimePicker(null);
fail("did not throw NullPointerException when param context is null.");
@@ -63,29 +63,31 @@
// expected
}
- new TimePicker(mContext, attrs);
+ new TimePicker(mActivity, attrs);
try {
new TimePicker(null, attrs);
fail("did not throw NullPointerException when param context is null.");
} catch (NullPointerException e) {
// expected
}
- new TimePicker(mContext, null);
+ new TimePicker(mActivity, null);
- new TimePicker(mContext, attrs, 0);
+ new TimePicker(mActivity, attrs, 0);
try {
new TimePicker(null, attrs, 0);
fail("did not throw NullPointerException when param context is null.");
} catch (NullPointerException e) {
// expected
}
- new TimePicker(mContext, null, 0);
- new TimePicker(mContext, attrs, 0);
- new TimePicker(mContext, attrs, Integer.MIN_VALUE);
+ new TimePicker(mActivity, null, 0);
+ new TimePicker(mActivity, attrs, 0);
+ new TimePicker(mActivity, null, android.R.attr.timePickerStyle);
+ new TimePicker(mActivity, null, 0, android.R.style.Widget_Material_TimePicker);
+ new TimePicker(mActivity, null, 0, android.R.style.Widget_Material_Light_TimePicker);
}
+ @UiThreadTest
public void testSetEnabled() {
- mTimePicker = new TimePicker(mContext);
assertTrue(mTimePicker.isEnabled());
mTimePicker.setEnabled(false);
@@ -96,49 +98,66 @@
}
public void testSetOnTimeChangedListener() {
- int initialHour = 13;
- int initialMinute = 50;
- mTimePicker = new TimePicker(mContext);
+ // On time change listener is notified on every call to setCurrentHour / setCurrentMinute.
+ // We want to make sure that before we register our listener, we initialize the time picker
+ // to the time that is explicitly different from the values we'll be testing for in both
+ // hour and minute. Otherwise if the test happens to run at the time that ends in
+ // "minuteForTesting" minutes, we'll get two onTimeChanged callbacks with identical values.
+ final int initialHour = 10;
+ final int initialMinute = 38;
+ final int hourForTesting = 13;
+ final int minuteForTesting = 50;
- MockOnTimeChangeListener listener = new MockOnTimeChangeListener();
- mTimePicker.setOnTimeChangedListener(listener);
- mTimePicker.setCurrentHour(Integer.valueOf(initialHour));
- mTimePicker.setCurrentMinute(Integer.valueOf(initialMinute));
- assertEquals(initialHour, listener.getNotifiedHourOfDay());
- assertEquals(initialMinute, listener.getNotifiedMinute());
+ mInstrumentation.runOnMainSync(() -> {
+ mTimePicker.setHour(initialHour);
+ mTimePicker.setMinute(initialMinute);
+ });
+
+ // Now register the listener
+ TimePicker.OnTimeChangedListener mockOnTimeChangeListener =
+ mock(TimePicker.OnTimeChangedListener.class);
+ mTimePicker.setOnTimeChangedListener(mockOnTimeChangeListener);
+ mInstrumentation.runOnMainSync(() -> {
+ mTimePicker.setCurrentHour(Integer.valueOf(hourForTesting));
+ mTimePicker.setCurrentMinute(Integer.valueOf(minuteForTesting));
+ });
+ // We're expecting two onTimeChanged callbacks, one with new hour and one with new
+ // hour+minute
+ verify(mockOnTimeChangeListener, times(1)).onTimeChanged(
+ mTimePicker, hourForTesting, initialMinute);
+ verify(mockOnTimeChangeListener, times(1)).onTimeChanged(
+ mTimePicker, hourForTesting, minuteForTesting);
// set the same hour as current
- listener.reset();
- mTimePicker.setCurrentHour(Integer.valueOf(initialHour));
- assertFalse(listener.hasCalledOnTimeChanged());
+ reset(mockOnTimeChangeListener);
+ mInstrumentation.runOnMainSync(
+ () -> mTimePicker.setCurrentHour(Integer.valueOf(hourForTesting)));
+ verifyZeroInteractions(mockOnTimeChangeListener);
- mTimePicker.setCurrentHour(Integer.valueOf(initialHour + 1));
- assertTrue(listener.hasCalledOnTimeChanged());
- assertEquals(initialHour + 1, listener.getNotifiedHourOfDay());
- assertEquals(initialMinute, listener.getNotifiedMinute());
- assertSame(mTimePicker, listener.getNotifiedView());
+ mInstrumentation.runOnMainSync(
+ () -> mTimePicker.setCurrentHour(Integer.valueOf(hourForTesting + 1)));
+ verify(mockOnTimeChangeListener, times(1)).onTimeChanged(
+ mTimePicker, hourForTesting + 1, minuteForTesting);
// set the same minute as current
- listener.reset();
- mTimePicker.setCurrentMinute(initialMinute);
- assertFalse(listener.hasCalledOnTimeChanged());
+ reset(mockOnTimeChangeListener);
+ mInstrumentation.runOnMainSync(() -> mTimePicker.setCurrentMinute(minuteForTesting));
+ verifyZeroInteractions(mockOnTimeChangeListener);
- listener.reset();
- mTimePicker.setCurrentMinute(initialMinute + 1);
- assertTrue(listener.hasCalledOnTimeChanged());
- assertEquals(initialHour + 1, listener.getNotifiedHourOfDay());
- assertEquals(initialMinute + 1, listener.getNotifiedMinute());
- assertSame(mTimePicker, listener.getNotifiedView());
+ reset(mockOnTimeChangeListener);
+ mInstrumentation.runOnMainSync(() -> mTimePicker.setCurrentMinute(minuteForTesting + 1));
+ verify(mockOnTimeChangeListener, times(1)).onTimeChanged(
+ mTimePicker, hourForTesting + 1, minuteForTesting + 1);
// change time picker mode
- listener.reset();
- mTimePicker.setIs24HourView( !mTimePicker.is24HourView() );
- assertFalse(listener.hasCalledOnTimeChanged());
+ reset(mockOnTimeChangeListener);
+ mInstrumentation.runOnMainSync(
+ () -> mTimePicker.setIs24HourView(!mTimePicker.is24HourView()));
+ verifyZeroInteractions(mockOnTimeChangeListener);
}
+ @UiThreadTest
public void testAccessCurrentHour() {
- mTimePicker = new TimePicker(mContext);
-
// AM/PM mode
mTimePicker.setIs24HourView(false);
@@ -167,9 +186,8 @@
assertEquals(Integer.valueOf(23), mTimePicker.getCurrentHour());
}
+ @UiThreadTest
public void testAccessHour() {
- mTimePicker = new TimePicker(mContext);
-
// AM/PM mode
mTimePicker.setIs24HourView(false);
@@ -198,8 +216,8 @@
assertEquals(23, mTimePicker.getHour());
}
+ @UiThreadTest
public void testAccessIs24HourView() {
- mTimePicker = new TimePicker(mContext);
assertFalse(mTimePicker.is24HourView());
mTimePicker.setIs24HourView(true);
@@ -209,9 +227,8 @@
assertFalse(mTimePicker.is24HourView());
}
+ @UiThreadTest
public void testAccessCurrentMinute() {
- mTimePicker = new TimePicker(mContext);
-
mTimePicker.setCurrentMinute(0);
assertEquals(Integer.valueOf(0), mTimePicker.getCurrentMinute());
@@ -225,9 +242,8 @@
assertEquals(Integer.valueOf(59), mTimePicker.getCurrentMinute());
}
+ @UiThreadTest
public void testAccessMinute() {
- mTimePicker = new TimePicker(mContext);
-
mTimePicker.setMinute(0);
assertEquals(0, mTimePicker.getMinute());
@@ -242,13 +258,12 @@
}
public void testGetBaseline() {
- mTimePicker = new TimePicker(mContext);
assertEquals(-1, mTimePicker.getBaseline());
}
public void testOnSaveInstanceStateAndOnRestoreInstanceState() {
- MyTimePicker source = new MyTimePicker(mContext);
- MyTimePicker dest = new MyTimePicker(mContext);
+ MyTimePicker source = new MyTimePicker(mActivity);
+ MyTimePicker dest = new MyTimePicker(mActivity);
int expectHour = (dest.getCurrentHour() + 10) % 24;
int expectMinute = (dest.getCurrentMinute() + 10) % 60;
source.setCurrentHour(expectHour);
@@ -261,46 +276,6 @@
assertEquals(Integer.valueOf(expectMinute), dest.getCurrentMinute());
}
- private class MockOnTimeChangeListener implements OnTimeChangedListener {
- private TimePicker mNotifiedView;
-
- private boolean mHasCalledOnTimeChanged;
-
- private int mNotifiedHourOfDay;
-
- private int mNotifiedMinute;;
-
- public boolean hasCalledOnTimeChanged() {
- return mHasCalledOnTimeChanged;
- }
-
- public TimePicker getNotifiedView() {
- return mNotifiedView;
- }
-
- public int getNotifiedHourOfDay() {
- return mNotifiedHourOfDay;
- }
-
- public int getNotifiedMinute() {
- return mNotifiedMinute;
- }
-
- public void reset() {
- mNotifiedView = null;
- mNotifiedHourOfDay = 0;
- mNotifiedMinute = 0;
- mHasCalledOnTimeChanged = false;
- }
-
- public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
- mNotifiedView = view;
- mNotifiedHourOfDay = hourOfDay;
- mNotifiedMinute = minute;
- mHasCalledOnTimeChanged = true;
- }
- }
-
private class MyTimePicker extends TimePicker {
public MyTimePicker(Context context) {
super(context);
diff --git a/tests/tests/widget/src/android/widget/cts/ToastTest.java b/tests/tests/widget/src/android/widget/cts/ToastTest.java
index 854247e..b029cc7 100644
--- a/tests/tests/widget/src/android/widget/cts/ToastTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToastTest.java
@@ -74,22 +74,12 @@
}
private void assertShowToast(final View view) {
- new PollingCheck(TIME_OUT) {
- @Override
- protected boolean check() {
- return null != view.getParent();
- }
- }.run();
+ PollingCheck.waitFor(TIME_OUT, () -> null != view.getParent());
}
private void assertShowAndHide(final View view) {
assertShowToast(view);
- new PollingCheck(TIME_OUT) {
- @Override
- protected boolean check() {
- return null == view.getParent();
- }
- }.run();
+ PollingCheck.waitFor(TIME_OUT, () -> null == view.getParent());
}
private void assertNotShowToast(final View view) throws InterruptedException {
@@ -104,12 +94,7 @@
}
private void assertLayoutDone(final View view) {
- new PollingCheck(TIME_OUT) {
- @Override
- protected boolean check() {
- return mLayoutDone;
- }
- }.run();
+ PollingCheck.waitFor(TIME_OUT, () -> mLayoutDone);
view.getViewTreeObserver().removeOnGlobalLayoutListener(mLayoutListener);
}
diff --git a/tests/tests/widget/src/android/widget/cts/ToggleButtonCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ToggleButtonCtsActivity.java
new file mode 100644
index 0000000..3640957
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ToggleButtonCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.ToggleButton;
+
+/**
+ * A minimal application for {@link ToggleButton} test.
+ */
+public class ToggleButtonCtsActivity extends Activity {
+ /**
+ * Called with the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.togglebutton_layout);
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/ToggleButtonTest.java b/tests/tests/widget/src/android/widget/cts/ToggleButtonTest.java
index d335c13..8d54b03 100644
--- a/tests/tests/widget/src/android/widget/cts/ToggleButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToggleButtonTest.java
@@ -16,6 +16,11 @@
package android.widget.cts;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.widget.RadioButton;
import org.xmlpull.v1.XmlPullParser;
import android.content.Context;
@@ -34,27 +39,35 @@
/**
* Test {@link ToggleButton}.
*/
-public class ToggleButtonTest extends InstrumentationTestCase {
+@SmallTest
+public class ToggleButtonTest extends ActivityInstrumentationTestCase2<ToggleButtonCtsActivity> {
private static final String TEXT_OFF = "text off";
private static final String TEXT_ON = "text on";
- ToggleButton mToggleButton;
- Context mContext;
- AttributeSet mAttrSet;
+
+ private Instrumentation mInstrumentation;
+ private Activity mActivity;
+
+ public ToggleButtonTest() {
+ super("android.widget.cts", ToggleButtonCtsActivity.class);
+ }
@Override
protected void setUp() throws Exception {
super.setUp();
- mContext = getInstrumentation().getTargetContext();
- XmlPullParser parser = mContext.getResources().getXml(R.layout.togglebutton_layout);
- mAttrSet = Xml.asAttributeSet(parser);
- mToggleButton = new ToggleButton(mContext, mAttrSet);
+ mInstrumentation = getInstrumentation();
+ mActivity = getActivity();
}
public void testConstructor() {
- new ToggleButton(mContext, mAttrSet, 0);
- new ToggleButton(mContext, mAttrSet);
- new ToggleButton(mContext);
+ new ToggleButton(mActivity);
+ new ToggleButton(mActivity, null);
+ new ToggleButton(mActivity, null, android.R.attr.buttonStyleToggle);
+ new ToggleButton(mActivity, null, 0, android.R.style.Widget_DeviceDefault_Button_Toggle);
+ new ToggleButton(mActivity, null, 0,
+ android.R.style.Widget_DeviceDefault_Light_Button_Toggle);
+ new ToggleButton(mActivity, null, 0, android.R.style.Widget_Material_Button_Toggle);
+ new ToggleButton(mActivity, null, 0, android.R.style.Widget_Material_Light_Button_Toggle);
try {
new ToggleButton(null, null, -1);
@@ -78,105 +91,127 @@
}
}
- public void testAccessTextOff() {
- mToggleButton.setTextOff("android");
- assertEquals("android", mToggleButton.getTextOff());
- mToggleButton.setChecked(false);
-
- mToggleButton.setTextOff(null);
- assertNull(mToggleButton.getTextOff());
-
- mToggleButton.setTextOff("");
- assertEquals("", mToggleButton.getTextOff());
+ public void testAttributesFromStyle() {
+ final ToggleButton toggleButton =
+ (ToggleButton) mActivity.findViewById(R.id.toggle_with_style);
+ assertEquals(mActivity.getString(R.string.toggle_text_on), toggleButton.getTextOn());
+ assertEquals(mActivity.getString(R.string.toggle_text_off), toggleButton.getTextOff());
}
- @UiThreadTest
+ public void testAttributesFromLayout() {
+ final ToggleButton toggleButton =
+ (ToggleButton) mActivity.findViewById(R.id.toggle_with_defaults);
+ assertEquals(mActivity.getString(R.string.toggle_text_on_alt), toggleButton.getTextOn());
+ assertEquals(mActivity.getString(R.string.toggle_text_off_alt), toggleButton.getTextOff());
+ }
+
+ public void testAccessTextOff() {
+ final ToggleButton toggleButton = (ToggleButton) mActivity.findViewById(R.id.toggle1);
+ mInstrumentation.runOnMainSync(() -> toggleButton.setTextOff("android"));
+ assertEquals("android", toggleButton.getTextOff());
+ mInstrumentation.runOnMainSync(() -> toggleButton.setChecked(false));
+
+ mInstrumentation.runOnMainSync(() -> toggleButton.setTextOff(null));
+ assertNull(toggleButton.getTextOff());
+
+ mInstrumentation.runOnMainSync(() -> toggleButton.setTextOff(""));
+ assertEquals("", toggleButton.getTextOff());
+ }
+
public void testDrawableStateChanged() {
- MockToggleButton toggleButton = new MockToggleButton(mContext);
+ final MockToggleButton toggleButton = new MockToggleButton(mActivity);
// drawableStateChanged without any drawable.
- toggleButton.drawableStateChanged();
+ mInstrumentation.runOnMainSync(() -> toggleButton.drawableStateChanged());
- StateListDrawable drawable = new StateListDrawable();
+ final StateListDrawable drawable = new StateListDrawable();
drawable.addState(new int[] { android.R.attr.state_pressed },
- mContext.getDrawable(R.drawable.scenery));
+ mActivity.getDrawable(R.drawable.scenery));
drawable.addState(new int[] {},
- mContext.getDrawable(R.drawable.scenery));
+ mActivity.getDrawable(R.drawable.scenery));
// drawableStateChanged when CheckMarkDrawable is not null.
- toggleButton.setButtonDrawable(drawable);
+ mInstrumentation.runOnMainSync(() -> toggleButton.setButtonDrawable(drawable));
drawable.setState(null);
assertNull(drawable.getState());
- toggleButton.drawableStateChanged();
+ mInstrumentation.runOnMainSync(() -> toggleButton.drawableStateChanged());
assertNotNull(drawable.getState());
assertEquals(toggleButton.getDrawableState(), drawable.getState());
}
public void testOnFinishInflate() {
- MockToggleButton toggleButton = new MockToggleButton(mContext);
+ MockToggleButton toggleButton = new MockToggleButton(mActivity);
toggleButton.onFinishInflate();
}
- @UiThreadTest
public void testSetChecked() {
- assertFalse(mToggleButton.isChecked());
+ final ToggleButton toggleButton = (ToggleButton) mActivity.findViewById(R.id.toggle1);
+ assertFalse(toggleButton.isChecked());
- mToggleButton.setChecked(true);
- assertTrue(mToggleButton.isChecked());
+ mInstrumentation.runOnMainSync(() -> toggleButton.setChecked(true));
+ assertTrue(toggleButton.isChecked());
- mToggleButton.setChecked(false);
- assertFalse(mToggleButton.isChecked());
+ mInstrumentation.runOnMainSync(() -> toggleButton.setChecked(false));
+ assertFalse(toggleButton.isChecked());
}
- @UiThreadTest
public void testToggleText() {
- mToggleButton.setText("default text");
- mToggleButton.setTextOn(TEXT_ON);
- mToggleButton.setTextOff(TEXT_OFF);
- mToggleButton.setChecked(true);
- assertEquals(TEXT_ON, mToggleButton.getText().toString());
- mToggleButton.setChecked(false);
- assertFalse(mToggleButton.isChecked());
- assertEquals(TEXT_OFF, mToggleButton.getText().toString());
+ final ToggleButton toggleButton = (ToggleButton) mActivity.findViewById(R.id.toggle1);
+ mInstrumentation.runOnMainSync(() -> {
+ toggleButton.setText("default text");
+ toggleButton.setTextOn(TEXT_ON);
+ toggleButton.setTextOff(TEXT_OFF);
+ toggleButton.setChecked(true);
+ });
+ assertEquals(TEXT_ON, toggleButton.getText().toString());
+ toggleButton.setChecked(false);
+ assertFalse(toggleButton.isChecked());
+ assertEquals(TEXT_OFF, toggleButton.getText().toString());
// Set the current displaying text as TEXT_OFF.
// Then set checked button, but textOn is null.
- mToggleButton.setTextOff(TEXT_OFF);
- mToggleButton.setChecked(false);
- mToggleButton.setTextOn(null);
- mToggleButton.setChecked(true);
- assertEquals(TEXT_OFF, mToggleButton.getText().toString());
+ mInstrumentation.runOnMainSync(() -> {
+ toggleButton.setTextOff(TEXT_OFF);
+ toggleButton.setChecked(false);
+ toggleButton.setTextOn(null);
+ toggleButton.setChecked(true);
+ });
+ assertEquals(TEXT_OFF, toggleButton.getText().toString());
// Set the current displaying text as TEXT_ON. Then set unchecked button,
// but textOff is null.
- mToggleButton.setTextOn(TEXT_ON);
- mToggleButton.setChecked(true);
- mToggleButton.setTextOff(null);
- mToggleButton.setChecked(false);
- assertEquals(TEXT_ON, mToggleButton.getText().toString());
+ mInstrumentation.runOnMainSync(() -> {
+ toggleButton.setTextOn(TEXT_ON);
+ toggleButton.setChecked(true);
+ toggleButton.setTextOff(null);
+ toggleButton.setChecked(false);
+ });
+ assertEquals(TEXT_ON, toggleButton.getText().toString());
}
public void testSetBackgroundDrawable() {
- Drawable drawable = mContext.getResources().getDrawable(R.drawable.scenery);
+ final ToggleButton toggleButton = (ToggleButton) mActivity.findViewById(R.id.toggle1);
+ final Drawable drawable = mActivity.getDrawable(R.drawable.scenery);
- mToggleButton.setBackgroundDrawable(drawable);
- assertSame(drawable, mToggleButton.getBackground());
+ mInstrumentation.runOnMainSync(() -> toggleButton.setBackgroundDrawable(drawable));
+ assertSame(drawable, toggleButton.getBackground());
// remove the background
- mToggleButton.setBackgroundDrawable(null);
- assertNull(mToggleButton.getBackground());
+ mInstrumentation.runOnMainSync(() -> toggleButton.setBackgroundDrawable(null));
+ assertNull(toggleButton.getBackground());
}
public void testAccessTextOn() {
- mToggleButton.setTextOn("cts");
- assertEquals("cts", mToggleButton.getTextOn());
+ final ToggleButton toggleButton = (ToggleButton) mActivity.findViewById(R.id.toggle1);
+ mInstrumentation.runOnMainSync(() -> toggleButton.setTextOn("cts"));
+ assertEquals("cts", toggleButton.getTextOn());
- mToggleButton.setTextOn(null);
- assertNull(mToggleButton.getTextOn());
+ mInstrumentation.runOnMainSync(() -> toggleButton.setTextOn(null));
+ assertNull(toggleButton.getTextOn());
- mToggleButton.setTextOn("");
- assertEquals("", mToggleButton.getTextOn());
+ mInstrumentation.runOnMainSync(() -> toggleButton.setTextOn(""));
+ assertEquals("", toggleButton.getTextOn());
}
/**
diff --git a/tests/tests/widget/src/android/widget/cts/ToolbarTest.java b/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
index 7f9690c..872e68c 100644
--- a/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
@@ -17,8 +17,6 @@
package android.widget.cts;
import android.app.Instrumentation;
-import android.content.Context;
-import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.test.ActivityInstrumentationTestCase2;
@@ -27,7 +25,6 @@
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-import android.widget.ListPopupWindow;
import android.widget.Toolbar;
import android.widget.cts.util.TestUtils;
import android.widget.cts.util.ViewTestUtils;
@@ -36,8 +33,9 @@
@MediumTest
public class ToolbarTest extends ActivityInstrumentationTestCase2<ToolbarCtsActivity> {
- private Toolbar mMainToolbar;
+ private Instrumentation mInstrumentation;
private ToolbarCtsActivity mActivity;
+ private Toolbar mMainToolbar;
public ToolbarTest() {
super("android.widget.cts", ToolbarCtsActivity.class);
@@ -46,6 +44,8 @@
@Override
protected void setUp() throws Exception {
super.setUp();
+
+ mInstrumentation = getInstrumentation();
mActivity = getActivity();
mMainToolbar = mActivity.getMainToolbar();
}
@@ -67,45 +67,41 @@
// of getTitle / getSubtitle, this logic follows the path of deferred layout
// and invalidation of the TextViews that show the title / subtitle in the Toolbar.
- final Instrumentation instrumentation = getInstrumentation();
-
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.setTitle(R.string.toolbar_title));
assertEquals(mActivity.getString(R.string.toolbar_title), mMainToolbar.getTitle());
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.setTitle("New title"));
assertEquals("New title", mMainToolbar.getTitle());
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.setSubtitle(R.string.toolbar_subtitle));
assertEquals(mActivity.getString(R.string.toolbar_subtitle), mMainToolbar.getSubtitle());
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.setSubtitle("New subtitle"));
assertEquals("New subtitle", mMainToolbar.getSubtitle());
}
public void testTitleAndSubtitleAppearance() {
- final Instrumentation instrumentation = getInstrumentation();
-
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.setTitle(R.string.toolbar_title));
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.setSubtitle(R.string.toolbar_subtitle));
// Since there are no APIs to get reference to the underlying implementation of
// title and subtitle, here we are testing that calling the relevant APIs doesn't crash
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.setTitleTextColor(Color.RED));
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.setSubtitleTextColor(Color.BLUE));
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.setTitleTextAppearance(
mActivity, R.style.TextAppearance_NotColors));
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.setSubtitleTextAppearance(
mActivity, R.style.TextAppearance_WithColor));
}
@@ -139,9 +135,7 @@
}
public void testMenuContent() {
- final Instrumentation instrumentation = getInstrumentation();
-
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
final Menu menu = mMainToolbar.getMenu();
@@ -170,34 +164,30 @@
}
public void testMenuOverflowShowHide() {
- final Instrumentation instrumentation = getInstrumentation();
-
// Inflate menu and check that we're not showing overflow menu yet
- instrumentation.runOnMainSync(() -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
assertFalse(mMainToolbar.isOverflowMenuShowing());
// Ask to show overflow menu and check that it's showing
- instrumentation.runOnMainSync(() -> mMainToolbar.showOverflowMenu());
- instrumentation.waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.showOverflowMenu());
+ mInstrumentation.waitForIdleSync();
assertTrue(mMainToolbar.isOverflowMenuShowing());
// Ask to hide the overflow menu and check that it's not showing
- instrumentation.runOnMainSync(() -> mMainToolbar.hideOverflowMenu());
- instrumentation.waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.hideOverflowMenu());
+ mInstrumentation.waitForIdleSync();
assertFalse(mMainToolbar.isOverflowMenuShowing());
}
public void testMenuOverflowSubmenu() {
- final Instrumentation instrumentation = getInstrumentation();
-
// Inflate menu and check that we're not showing overflow menu yet
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
assertFalse(mMainToolbar.isOverflowMenuShowing());
// Ask to show overflow menu and check that it's showing
- instrumentation.runOnMainSync(() -> mMainToolbar.showOverflowMenu());
- instrumentation.waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.showOverflowMenu());
+ mInstrumentation.waitForIdleSync();
assertTrue(mMainToolbar.isOverflowMenuShowing());
// Register a mock menu item click listener on the toolbar
@@ -209,162 +199,256 @@
// Ask to "perform" the share action and check that the menu click listener has
// been notified
- instrumentation.runOnMainSync(() -> menu.performIdentifierAction(R.id.action_share, 0));
+ mInstrumentation.runOnMainSync(() -> menu.performIdentifierAction(R.id.action_share, 0));
verify(menuItemClickListener, times(1)).onMenuItemClick(
menu.findItem(R.id.action_share));
// Ask to dismiss all the popups and check that we're not showing the overflow menu
- instrumentation.runOnMainSync(() -> mMainToolbar.dismissPopupMenus());
- instrumentation.waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.dismissPopupMenus());
+ mInstrumentation.waitForIdleSync();
assertFalse(mMainToolbar.isOverflowMenuShowing());
}
public void testMenuOverflowIcon() {
- final Instrumentation instrumentation = getInstrumentation();
-
// Inflate menu and check that we're not showing overflow menu yet
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
final Drawable overflowIcon = mActivity.getDrawable(R.drawable.icon_red);
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.setOverflowIcon(overflowIcon));
final Drawable toolbarOverflowIcon = mMainToolbar.getOverflowIcon();
TestUtils.assertAllPixelsOfColor("Overflow icon is red", toolbarOverflowIcon,
toolbarOverflowIcon.getIntrinsicWidth(), toolbarOverflowIcon.getIntrinsicHeight(),
- true, 0XFFFF0000, 1, false);
+ true, Color.RED, 1, false);
}
public void testActionView() {
- final Instrumentation instrumentation = getInstrumentation();
-
// Inflate menu and check that we don't have an expanded action view
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.inflateMenu(R.menu.toolbar_menu_search));
assertFalse(mMainToolbar.hasExpandedActionView());
// Expand search menu item's action view and verify that main toolbar has an expanded
// action view
final MenuItem searchMenuItem = mMainToolbar.getMenu().findItem(R.id.action_search);
- instrumentation.runOnMainSync(() -> searchMenuItem.expandActionView());
- instrumentation.waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> searchMenuItem.expandActionView());
+ mInstrumentation.waitForIdleSync();
assertTrue(searchMenuItem.isActionViewExpanded());
assertTrue(mMainToolbar.hasExpandedActionView());
// Collapse search menu item's action view and verify that main toolbar doesn't have an
// expanded action view
- instrumentation.runOnMainSync(() -> searchMenuItem.collapseActionView());
- instrumentation.waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> searchMenuItem.collapseActionView());
+ mInstrumentation.waitForIdleSync();
assertFalse(searchMenuItem.isActionViewExpanded());
assertFalse(mMainToolbar.hasExpandedActionView());
// Expand search menu item's action view again
- instrumentation.runOnMainSync(() -> searchMenuItem.expandActionView());
- instrumentation.waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> searchMenuItem.expandActionView());
+ mInstrumentation.waitForIdleSync();
assertTrue(searchMenuItem.isActionViewExpanded());
assertTrue(mMainToolbar.hasExpandedActionView());
// Now collapse search menu item's action view via toolbar's API and verify that main
// toolbar doesn't have an expanded action view
- instrumentation.runOnMainSync(() -> mMainToolbar.collapseActionView());
- instrumentation.waitForIdleSync();
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.collapseActionView());
+ mInstrumentation.waitForIdleSync();
assertFalse(searchMenuItem.isActionViewExpanded());
assertFalse(mMainToolbar.hasExpandedActionView());
}
public void testNavigationConfiguration() {
- final Instrumentation instrumentation = getInstrumentation();
-
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.setNavigationIcon(R.drawable.icon_green));
Drawable toolbarNavigationIcon = mMainToolbar.getNavigationIcon();
TestUtils.assertAllPixelsOfColor("Navigation icon is green", toolbarNavigationIcon,
toolbarNavigationIcon.getIntrinsicWidth(),
toolbarNavigationIcon.getIntrinsicHeight(),
- true, 0xFF00FF00, 1, false);
+ true, Color.GREEN, 1, false);
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.setNavigationIcon(mActivity.getDrawable(R.drawable.icon_blue)));
toolbarNavigationIcon = mMainToolbar.getNavigationIcon();
TestUtils.assertAllPixelsOfColor("Navigation icon is blue", toolbarNavigationIcon,
toolbarNavigationIcon.getIntrinsicWidth(),
toolbarNavigationIcon.getIntrinsicHeight(),
- true, 0xFF0000FF, 1, false);
+ true, Color.BLUE, 1, false);
- instrumentation.runOnMainSync(
+ mInstrumentation.runOnMainSync(
() -> mMainToolbar.setNavigationContentDescription(R.string.toolbar_navigation));
assertEquals(mActivity.getResources().getString(R.string.toolbar_navigation),
mMainToolbar.getNavigationContentDescription());
- instrumentation.runOnMainSync(
+ mInstrumentation.runOnMainSync(
() -> mMainToolbar.setNavigationContentDescription("Navigation legend"));
assertEquals("Navigation legend", mMainToolbar.getNavigationContentDescription());
}
public void testLogoConfiguration() {
- final Instrumentation instrumentation = getInstrumentation();
-
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.setLogo(R.drawable.icon_yellow));
Drawable toolbarLogo = mMainToolbar.getLogo();
TestUtils.assertAllPixelsOfColor("Logo is yellow", toolbarLogo,
toolbarLogo.getIntrinsicWidth(),
toolbarLogo.getIntrinsicHeight(),
- true, 0xFFFFFF00, 1, false);
+ true, Color.YELLOW, 1, false);
- ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
() -> mMainToolbar.setLogo(mActivity.getDrawable(R.drawable.icon_red)));
toolbarLogo = mMainToolbar.getLogo();
TestUtils.assertAllPixelsOfColor("Logo is red", toolbarLogo,
toolbarLogo.getIntrinsicWidth(),
toolbarLogo.getIntrinsicHeight(),
- true, 0xFFFF0000, 1, false);
+ true, Color.RED, 1, false);
- instrumentation.runOnMainSync(
+ mInstrumentation.runOnMainSync(
() -> mMainToolbar.setLogoDescription(R.string.toolbar_logo));
assertEquals(mActivity.getResources().getString(R.string.toolbar_logo),
mMainToolbar.getLogoDescription());
- instrumentation.runOnMainSync(
+ mInstrumentation.runOnMainSync(
() -> mMainToolbar.setLogoDescription("Logo legend"));
assertEquals("Logo legend", mMainToolbar.getLogoDescription());
}
- @UiThreadTest
public void testContentInsetsLtr() {
- mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
+ mInstrumentation.runOnMainSync(
+ () -> mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
- mMainToolbar.setContentInsetsAbsolute(20, 25);
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsAbsolute(20, 25));
assertEquals(20, mMainToolbar.getContentInsetLeft());
assertEquals(20, mMainToolbar.getContentInsetStart());
assertEquals(25, mMainToolbar.getContentInsetRight());
assertEquals(25, mMainToolbar.getContentInsetEnd());
- mMainToolbar.setContentInsetsRelative(40, 20);
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsRelative(40, 20));
assertEquals(40, mMainToolbar.getContentInsetLeft());
assertEquals(40, mMainToolbar.getContentInsetStart());
assertEquals(20, mMainToolbar.getContentInsetRight());
assertEquals(20, mMainToolbar.getContentInsetEnd());
}
- @UiThreadTest
public void testContentInsetsRtl() {
- mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
+ mInstrumentation.runOnMainSync(
+ () -> mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_RTL));
- mMainToolbar.setContentInsetsAbsolute(20, 25);
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsAbsolute(20, 25));
assertEquals(20, mMainToolbar.getContentInsetLeft());
assertEquals(25, mMainToolbar.getContentInsetStart());
assertEquals(25, mMainToolbar.getContentInsetRight());
assertEquals(20, mMainToolbar.getContentInsetEnd());
- mMainToolbar.setContentInsetsRelative(40, 20);
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsRelative(40, 20));
assertEquals(20, mMainToolbar.getContentInsetLeft());
assertEquals(40, mMainToolbar.getContentInsetStart());
assertEquals(40, mMainToolbar.getContentInsetRight());
assertEquals(20, mMainToolbar.getContentInsetEnd());
}
+ public void testCurrentContentInsetsLtr() {
+ mInstrumentation.runOnMainSync(
+ () -> mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_LTR));
+
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsRelative(20, 25));
+ assertEquals(20, mMainToolbar.getCurrentContentInsetLeft());
+ assertEquals(20, mMainToolbar.getCurrentContentInsetStart());
+ assertEquals(25, mMainToolbar.getCurrentContentInsetRight());
+ assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetStartWithNavigation(50));
+ assertEquals(50, mMainToolbar.getContentInsetStartWithNavigation());
+ // Since we haven't configured the navigation icon itself, the current content insets
+ // should stay the same
+ assertEquals(20, mMainToolbar.getCurrentContentInsetLeft());
+ assertEquals(20, mMainToolbar.getCurrentContentInsetStart());
+ assertEquals(25, mMainToolbar.getCurrentContentInsetRight());
+ assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
+ () -> mMainToolbar.setNavigationIcon(R.drawable.icon_green));
+ assertEquals(50, mMainToolbar.getContentInsetStartWithNavigation());
+ // Since we have configured the navigation icon, and the currently set start inset with
+ // navigation is bigger than currently set start content inset, we should be getting that
+ // bigger value now
+ assertEquals(50, mMainToolbar.getCurrentContentInsetLeft());
+ assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+ assertEquals(25, mMainToolbar.getCurrentContentInsetRight());
+ assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetEndWithActions(35));
+ assertEquals(35, mMainToolbar.getContentInsetEndWithActions());
+ // Since we haven't configured the menu content, the current content insets
+ // should stay the same
+ assertEquals(50, mMainToolbar.getCurrentContentInsetLeft());
+ assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+ assertEquals(25, mMainToolbar.getCurrentContentInsetRight());
+ assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
+ () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
+ assertEquals(35, mMainToolbar.getContentInsetEndWithActions());
+ // Since we have configured the menu content, and the currently set start inset with
+ // navigation is bigger than currently set end content inset, we should be getting that
+ // bigger value now
+ assertEquals(50, mMainToolbar.getCurrentContentInsetLeft());
+ assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+ assertEquals(35, mMainToolbar.getCurrentContentInsetRight());
+ assertEquals(35, mMainToolbar.getCurrentContentInsetEnd());
+ }
+
+ public void testCurrentContentInsetsRtl() {
+ mInstrumentation.runOnMainSync(
+ () -> mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_RTL));
+
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetsRelative(20, 25));
+ assertEquals(25, mMainToolbar.getCurrentContentInsetLeft());
+ assertEquals(20, mMainToolbar.getCurrentContentInsetStart());
+ assertEquals(20, mMainToolbar.getCurrentContentInsetRight());
+ assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetStartWithNavigation(50));
+ assertEquals(50, mMainToolbar.getContentInsetStartWithNavigation());
+ // Since we haven't configured the navigation icon itself, the current content insets
+ // should stay the same
+ assertEquals(25, mMainToolbar.getCurrentContentInsetLeft());
+ assertEquals(20, mMainToolbar.getCurrentContentInsetStart());
+ assertEquals(20, mMainToolbar.getCurrentContentInsetRight());
+ assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
+ () -> mMainToolbar.setNavigationIcon(R.drawable.icon_green));
+ assertEquals(50, mMainToolbar.getContentInsetStartWithNavigation());
+ // Since we have configured the navigation icon, and the currently set start inset with
+ // navigation is bigger than currently set start content inset, we should be getting that
+ // bigger value now
+ assertEquals(25, mMainToolbar.getCurrentContentInsetLeft());
+ assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+ assertEquals(50, mMainToolbar.getCurrentContentInsetRight());
+ assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.setContentInsetEndWithActions(35));
+ assertEquals(35, mMainToolbar.getContentInsetEndWithActions());
+ // Since we haven't configured the menu content, the current content insets
+ // should stay the same
+ assertEquals(25, mMainToolbar.getCurrentContentInsetLeft());
+ assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+ assertEquals(50, mMainToolbar.getCurrentContentInsetRight());
+ assertEquals(25, mMainToolbar.getCurrentContentInsetEnd());
+
+ ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mMainToolbar,
+ () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu));
+ assertEquals(35, mMainToolbar.getContentInsetEndWithActions());
+ // Since we have configured the menu content, and the currently set start inset with
+ // navigation is bigger than currently set end content inset, we should be getting that
+ // bigger value now
+ assertEquals(35, mMainToolbar.getCurrentContentInsetLeft());
+ assertEquals(50, mMainToolbar.getCurrentContentInsetStart());
+ assertEquals(50, mMainToolbar.getCurrentContentInsetRight());
+ assertEquals(35, mMainToolbar.getCurrentContentInsetEnd());
+ }
+
@UiThreadTest
public void testPopupTheme() {
mMainToolbar.setPopupTheme(R.style.ToolbarPopupTheme_Test);
@@ -377,7 +461,7 @@
verify(mockListener, never()).onClick(any(View.class));
- getInstrumentation().runOnMainSync(() -> mMainToolbar.getNavigationView().performClick());
+ mInstrumentation.runOnMainSync(() -> mMainToolbar.getNavigationView().performClick());
verify(mockListener, times(1)).onClick(any(View.class));
verifyNoMoreInteractions(mockListener);
diff --git a/tests/tests/widget/src/android/widget/cts/VideoViewTest.java b/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
index 265b802..7bb2ef8 100644
--- a/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
@@ -16,19 +16,11 @@
package android.widget.cts;
-import android.widget.cts.R;
-
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.cts.util.MediaUtils;
-import android.cts.util.PollingCheck;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecList;
import android.media.MediaPlayer;
-import android.media.MediaPlayer.OnCompletionListener;
-import android.media.MediaPlayer.OnErrorListener;
-import android.media.MediaPlayer.OnPreparedListener;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
import android.util.Log;
@@ -36,9 +28,16 @@
import android.widget.MediaController;
import android.widget.VideoView;
+import org.mockito.invocation.InvocationOnMock;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
/**
* Test {@link VideoView}.
@@ -63,43 +62,6 @@
private Instrumentation mInstrumentation;
private String mVideoPath;
- private static class MockListener {
- private boolean mTriggered;
-
- MockListener() {
- mTriggered = false;
- }
-
- public boolean isTriggered() {
- return mTriggered;
- }
-
- protected void onEvent() {
- mTriggered = true;
- }
- }
-
- private static class MockOnPreparedListener extends MockListener
- implements OnPreparedListener {
- public void onPrepared(MediaPlayer mp) {
- super.onEvent();
- }
- }
-
- private static class MockOnErrorListener extends MockListener implements OnErrorListener {
- public boolean onError(MediaPlayer mp, int what, int extra) {
- super.onEvent();
- return false;
- }
- }
-
- private static class MockOnCompletionListener extends MockListener
- implements OnCompletionListener {
- public void onCompletion(MediaPlayer mp) {
- super.onEvent();
- }
- }
-
private boolean hasCodec() {
return MediaUtils.hasCodecsForResource(mActivity, R.raw.testvideo);
}
@@ -190,42 +152,46 @@
return;
}
- final MockOnPreparedListener preparedListener = new MockOnPreparedListener();
- mVideoView.setOnPreparedListener(preparedListener);
- final MockOnCompletionListener completionListener = new MockOnCompletionListener();
- mVideoView.setOnCompletionListener(completionListener);
+ final MediaPlayer.OnPreparedListener mockPreparedListener =
+ mock(MediaPlayer.OnPreparedListener.class);
+ final CountDownLatch preparedLatch = new CountDownLatch(1);
+ doAnswer((InvocationOnMock invocation) -> {
+ preparedLatch.countDown();
+ return null;
+ }).when(mockPreparedListener).onPrepared(any(MediaPlayer.class));
+ mVideoView.setOnPreparedListener(mockPreparedListener);
- runTestOnUiThread(new Runnable() {
- public void run() {
- mVideoView.setVideoPath(mVideoPath);
- }
- });
- new PollingCheck(TIME_OUT) {
- @Override
- protected boolean check() {
- return preparedListener.isTriggered();
- }
- }.run();
- assertFalse(completionListener.isTriggered());
+ final MediaPlayer.OnCompletionListener mockCompletionListener =
+ mock(MediaPlayer.OnCompletionListener.class);
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+ doAnswer((InvocationOnMock invocation) -> {
+ completionLatch.countDown();
+ return null;
+ }).when(mockCompletionListener).onCompletion(any(MediaPlayer.class));
+ mVideoView.setOnCompletionListener(mockCompletionListener);
- runTestOnUiThread(new Runnable() {
- public void run() {
- mVideoView.start();
- }
- });
+ runTestOnUiThread(() -> mVideoView.setVideoPath(mVideoPath));
+ preparedLatch.await(TIME_OUT, TimeUnit.MILLISECONDS);
+ verify(mockPreparedListener, times(1)).onPrepared(any(MediaPlayer.class));
+ verifyZeroInteractions(mockCompletionListener);
+
+ runTestOnUiThread(() -> mVideoView.start());
// wait time is longer than duration in case system is sluggish
- new PollingCheck(mVideoView.getDuration() + TIME_OUT) {
- @Override
- protected boolean check() {
- return completionListener.isTriggered();
- }
- }.run();
+ completionLatch.await(mVideoView.getDuration() + TIME_OUT, TimeUnit.MILLISECONDS);
+ verify(mockCompletionListener, times(1)).onCompletion(any(MediaPlayer.class));
}
public void testSetOnErrorListener() throws Throwable {
makeVideoView();
- final MockOnErrorListener listener = new MockOnErrorListener();
- mVideoView.setOnErrorListener(listener);
+
+ final MediaPlayer.OnErrorListener mockErrorListener =
+ mock(MediaPlayer.OnErrorListener.class);
+ final CountDownLatch errorLatch = new CountDownLatch(1);
+ doAnswer((InvocationOnMock invocation) -> {
+ errorLatch.countDown();
+ return null;
+ }).when(mockErrorListener).onError(any(MediaPlayer.class), anyInt(), anyInt());
+ mVideoView.setOnErrorListener(mockErrorListener);
runTestOnUiThread(new Runnable() {
public void run() {
@@ -236,12 +202,8 @@
});
mInstrumentation.waitForIdleSync();
- new PollingCheck(TIME_OUT) {
- @Override
- protected boolean check() {
- return listener.isTriggered();
- }
- }.run();
+ errorLatch.await(TIME_OUT, TimeUnit.MILLISECONDS);
+ verify(mockErrorListener, times(1)).onError(any(MediaPlayer.class), anyInt(), anyInt());
}
public void testGetBufferPercentage() throws Throwable {
@@ -252,22 +214,20 @@
return;
}
- final MockOnPreparedListener prepareListener = new MockOnPreparedListener();
- mVideoView.setOnPreparedListener(prepareListener);
+ final MediaPlayer.OnPreparedListener mockPreparedListener =
+ mock(MediaPlayer.OnPreparedListener.class);
+ final CountDownLatch preparedLatch = new CountDownLatch(1);
+ doAnswer((InvocationOnMock invocation) -> {
+ preparedLatch.countDown();
+ return null;
+ }).when(mockPreparedListener).onPrepared(any(MediaPlayer.class));
+ mVideoView.setOnPreparedListener(mockPreparedListener);
- runTestOnUiThread(new Runnable() {
- public void run() {
- mVideoView.setVideoPath(mVideoPath);
- }
- });
+ runTestOnUiThread(() -> mVideoView.setVideoPath(mVideoPath));
mInstrumentation.waitForIdleSync();
- new PollingCheck(TIME_OUT) {
- @Override
- protected boolean check() {
- return prepareListener.isTriggered();
- }
- }.run();
+ preparedLatch.await(TIME_OUT, TimeUnit.MILLISECONDS);
+ verify(mockPreparedListener, times(1)).onPrepared(any(MediaPlayer.class));
int percent = mVideoView.getBufferPercentage();
assertTrue(percent >= 0 && percent <= 100);
}
@@ -295,11 +255,7 @@
return;
}
- runTestOnUiThread(new Runnable() {
- public void run() {
- mVideoView.setVideoPath(mVideoPath);
- }
- });
+ runTestOnUiThread(() -> mVideoView.setVideoPath(mVideoPath));
waitForOperationComplete();
assertTrue(Math.abs(mVideoView.getDuration() - TEST_VIDEO_DURATION) < DURATION_DELTA);
}
diff --git a/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java b/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
index 493c484..4cedd4f 100644
--- a/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
@@ -16,23 +16,28 @@
package android.widget.cts;
-import android.widget.cts.R;
-
-
-import org.xmlpull.v1.XmlPullParser;
-
import android.app.Activity;
-import android.cts.util.PollingCheck;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
import android.util.AttributeSet;
import android.util.Xml;
import android.view.View;
-import android.view.View.OnClickListener;
+import android.view.ViewConfiguration;
import android.widget.ListView;
import android.widget.ZoomButton;
+import android.widget.cts.util.ViewTestUtils;
+import org.xmlpull.v1.XmlPullParser;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@SmallTest
public class ZoomButtonTest extends ActivityInstrumentationTestCase2<ZoomButtonCtsActivity> {
+ private static long NANOS_IN_MILLI = 1000000;
private ZoomButton mZoomButton;
private Activity mActivity;
@@ -54,7 +59,9 @@
new ZoomButton(mActivity, null);
- new ZoomButton(mActivity, null, 0);
+ new ZoomButton(mActivity, null, android.R.attr.imageButtonStyle);
+
+ new ZoomButton(mActivity, null, 0, android.R.style.Widget_Material_Light_ImageButton);
XmlPullParser parser = mActivity.getResources().getXml(R.layout.zoombutton_layout);
AttributeSet attrs = Xml.asAttributeSet(parser);
@@ -81,6 +88,7 @@
}
}
+ @UiThreadTest
public void testSetEnabled() {
assertFalse(mZoomButton.isPressed());
mZoomButton.setEnabled(true);
@@ -105,21 +113,54 @@
assertFalse(mZoomButton.dispatchUnhandledMove(null, View.FOCUS_DOWN));
}
- public void testOnLongClick() {
- final MockOnClickListener listener = new MockOnClickListener();
- mZoomButton.setOnClickListener(listener);
- mZoomButton.setEnabled(true);
- long speed = 2000;
- mZoomButton.setZoomSpeed(speed);
+ private void verifyZoomSpeed(ZoomClickListener zoomClickListener, long zoomSpeedMs) {
+ mZoomButton.setZoomSpeed(zoomSpeedMs);
- assertFalse(listener.hasOnClickCalled());
- mZoomButton.performLongClick();
- new PollingCheck(speed + 500) {
- @Override
- protected boolean check() {
- return listener.hasOnClickCalled();
+ final long startTime = System.nanoTime();
+ // Emulate long click that "lasts" for ten seconds
+ ViewTestUtils.emulateLongClick(getInstrumentation(), mZoomButton, 10000);
+
+ final List<Long> callbackInvocations = zoomClickListener.getClickTimes();
+ assertFalse("Expecting at least one callback", callbackInvocations.isEmpty());
+
+ // Verify that the first callback is fired after the system-level long press timeout.
+ final long minTimeUntilFirstInvocationMs = ViewConfiguration.getLongPressTimeout();
+ final long actualTimeUntilFirstInvocationNs = callbackInvocations.get(0) - startTime;
+ assertTrue("First callback not during long press timeout was " +
+ actualTimeUntilFirstInvocationNs / NANOS_IN_MILLI +
+ " while long press timeout is " + minTimeUntilFirstInvocationMs,
+ (callbackInvocations.get(0) - startTime) >
+ minTimeUntilFirstInvocationMs * NANOS_IN_MILLI);
+
+ // Verify that subsequent callbacks are at least zoom-speed milliseconds apart. Note that
+ // we do not have any hard guarantee about the max limit on the time between successive
+ // callbacks.
+ final long minTimeBetweenInvocationsNs = zoomSpeedMs * NANOS_IN_MILLI;
+ if (callbackInvocations.size() > 1) {
+ for (int i = 0; i < callbackInvocations.size() - 1; i++) {
+ final long actualTimeBetweenInvocationsNs =
+ (callbackInvocations.get(i + 1) - callbackInvocations.get(i)) *
+ NANOS_IN_MILLI;
+ assertTrue("Callback " + (i + 1) + " happened " +
+ actualTimeBetweenInvocationsNs / NANOS_IN_MILLI +
+ " after the previous one, while zoom speed is " + zoomSpeedMs,
+ actualTimeBetweenInvocationsNs > minTimeBetweenInvocationsNs);
}
- };
+ }
+ }
+
+ @LargeTest
+ public void testOnLongClick() {
+ // Since Mockito doesn't have utilities to track the timestamps of method invocations,
+ // we're using our own custom click listener for that. We want to verify that the
+ // first listener invocation was after long press timeout, and the rest were spaced
+ // by at least our zoom speed milliseconds
+
+ mZoomButton.setEnabled(true);
+ ZoomClickListener zoomClickListener = new ZoomClickListener();
+ mZoomButton.setOnClickListener(zoomClickListener);
+
+ verifyZoomSpeed(zoomClickListener, 2000);
}
public void testOnTouchEvent() {
@@ -130,22 +171,35 @@
// Do not test. Implementation details.
}
+ @LargeTest
public void testSetZoomSpeed() {
- mZoomButton.setZoomSpeed(100);
+ final long[] zoomSpeeds = { 100, -1, 5000, 1000, 2500 };
+ mZoomButton.setEnabled(true);
+ ZoomClickListener zoomClickListener = new ZoomClickListener();
+ mZoomButton.setOnClickListener(zoomClickListener);
- mZoomButton.setZoomSpeed(-1);
- // TODO: how to check?
+ for (long zoomSpeed : zoomSpeeds) {
+ // Reset the tracker list of our listener, but continue using it for testing
+ // various zoom speeds on the same ZoomButton
+ zoomClickListener.reset();
+ verifyZoomSpeed(zoomClickListener, zoomSpeed);
+ }
}
- private static class MockOnClickListener implements OnClickListener {
- private boolean mOnClickCalled = false;
+ private static class ZoomClickListener implements View.OnClickListener {
+ private List<Long> mClickTimes = new ArrayList<>();
- public boolean hasOnClickCalled() {
- return mOnClickCalled;
+ public void reset() {
+ mClickTimes.clear();
+ }
+
+ public List<Long> getClickTimes() {
+ return Collections.unmodifiableList(mClickTimes);
}
public void onClick(View v) {
- mOnClickCalled = true;
+ // Add the current system time to the tracker list
+ mClickTimes.add(System.nanoTime());
}
}
-}
+}
\ No newline at end of file
diff --git a/tests/tests/widget/src/android/widget/cts/util/ExpandableListScenario.java b/tests/tests/widget/src/android/widget/cts/util/ExpandableListScenario.java
index 1b2eb15..7e72e88 100644
--- a/tests/tests/widget/src/android/widget/cts/util/ExpandableListScenario.java
+++ b/tests/tests/widget/src/android/widget/cts/util/ExpandableListScenario.java
@@ -54,7 +54,10 @@
@Override
protected void setAdapter(ListView listView) {
- ((ExpandableListView) listView).setAdapter(mAdapter = createAdapter());
+ mAdapter = createAdapter();
+ if (mAdapter != null) {
+ ((ExpandableListView) listView).setAdapter(mAdapter);
+ }
}
protected ExpandableListAdapter createAdapter() {
@@ -91,7 +94,7 @@
/**
* Sets the number of children per group.
*
- * @param numChildrenPerGroup The number of children per group.
+ * @param numChildren The number of children per group.
*/
public ExpandableParams setNumChildren(int[] numChildren) {
mNumChildren = numChildren;
@@ -275,6 +278,10 @@
* @return A group index with the requirements.
*/
public int findGroupWithNumChildren(int numChildren, boolean atLeastOneChild) {
+ if (mAdapter == null) {
+ return -1;
+ }
+
final ExpandableListAdapter adapter = mAdapter;
for (int i = adapter.getGroupCount() - 1; i >= 0; i--) {
@@ -292,10 +299,6 @@
return mGroups;
}
- public ExpandableListAdapter getAdapter() {
- return mAdapter;
- }
-
/**
* Simple expandable list adapter.
*/
@@ -348,10 +351,10 @@
}
public static class MyGroup {
- private static long mNextId = 1000;
+ private static long sNextId = 1000;
String name;
- long id = mNextId++;
+ long id = sNextId++;
List<MyChild> children;
public MyGroup(int numChildren) {
diff --git a/tests/tests/widget/src/android/widget/cts/util/ListScenario.java b/tests/tests/widget/src/android/widget/cts/util/ListScenario.java
index b61673c..c4d4199 100644
--- a/tests/tests/widget/src/android/widget/cts/util/ListScenario.java
+++ b/tests/tests/widget/src/android/widget/cts/util/ListScenario.java
@@ -79,10 +79,6 @@
return mListView;
}
- protected int getScreenHeight() {
- return mScreenHeight;
- }
-
/**
* Return whether the item at position is selectable (i.e is a separator).
* (external users can access this info using the adapter)
@@ -288,15 +284,6 @@
setClickedPosition(position);
}
- /**
- * Override this if you want to know when something has been long clicked (perhaps
- * more importantly, that {@link android.widget.AdapterView.OnItemLongClickListener} has
- * been triggered).
- */
- protected void positionLongClicked(int position) {
- setLongClickedPosition(position);
- }
-
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -353,11 +340,13 @@
}
});
- mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- public void onItemClick(AdapterView parent, View v, int position, long id) {
- positionClicked(position);
- }
- });
+ if (shouldRegisterItemClickListener()) {
+ mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ public void onItemClick(AdapterView parent, View v, int position, long id) {
+ positionClicked(position);
+ }
+ });
+ }
// set the fading edge length porportionally to the screen
// height for test stability
@@ -404,25 +393,11 @@
}
/**
- * Returns the LinearLayout containing the ListView in this scenario.
- *
- * @return The LinearLayout in which the ListView is held.
+ * Override to return false if you don't want the activity to register a default item click
+ * listener that redirects clicks to {@link #positionClicked(int)}.
*/
- protected LinearLayout getListViewContainer() {
- return mLinearLayout;
- }
-
- /**
- * Attaches a long press listener. You can find out which views were clicked by calling
- * {@link #getLongClickedPosition()}.
- */
- public void enableLongPress() {
- mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
- public boolean onItemLongClick(AdapterView parent, View v, int position, long id) {
- positionLongClicked(position);
- return true;
- }
- });
+ protected boolean shouldRegisterItemClickListener() {
+ return true;
}
/**
diff --git a/tests/tests/widget/src/android/widget/cts/util/TestUtils.java b/tests/tests/widget/src/android/widget/cts/util/TestUtils.java
index 8d8f573..2a043f6 100644
--- a/tests/tests/widget/src/android/widget/cts/util/TestUtils.java
+++ b/tests/tests/widget/src/android/widget/cts/util/TestUtils.java
@@ -16,20 +16,30 @@
package android.widget.cts.util;
+import android.annotation.ColorInt;
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.support.annotation.ColorInt;
-import android.support.annotation.NonNull;
+import android.text.Editable;
+import android.text.TextUtils;
import android.util.Pair;
import android.view.View;
import android.view.ViewParent;
import junit.framework.Assert;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import static org.mockito.Matchers.argThat;
+
public class TestUtils {
/**
* This method takes a view and returns a single bitmap that is the layered combination
@@ -100,7 +110,8 @@
}
/**
- * Checks whether all the pixels in the specified View are of the same specified color.
+ * Checks whether all the pixels in the specified of the {@link View} are
+ * filled with the specific color.
*
* In case there is a color mismatch, the behavior of this method depends on the
* <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
@@ -109,7 +120,26 @@
*/
public static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull View view,
@ColorInt int color, int allowedComponentVariance, boolean throwExceptionIfFails) {
+ assertRegionPixelsOfColor(failMessagePrefix, view,
+ new Rect(0, 0, view.getWidth(), view.getHeight()),
+ color, allowedComponentVariance, throwExceptionIfFails);
+ }
+
+ /**
+ * Checks whether all the pixels in the specific rectangular region of the {@link View} are
+ * filled with the specific color.
+ *
+ * In case there is a color mismatch, the behavior of this method depends on the
+ * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
+ * throw an <code>Exception</code> describing the mismatch. Otherwise this method will call
+ * <code>Assert.fail</code> with detailed description of the mismatch.
+ */
+ public static void assertRegionPixelsOfColor(String failMessagePrefix, @NonNull View view,
+ @NonNull Rect region, @ColorInt int color, int allowedComponentVariance,
+ boolean throwExceptionIfFails) {
// Create a bitmap
+ final int viewWidth = view.getWidth();
+ final int viewHeight = view.getHeight();
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),
Bitmap.Config.ARGB_8888);
// Create a canvas that wraps the bitmap
@@ -118,7 +148,7 @@
view.draw(canvas);
try {
- assertAllPixelsOfColor(failMessagePrefix, bitmap, view.getWidth(), view.getHeight(),
+ assertAllPixelsOfColor(failMessagePrefix, bitmap, region,
color, allowedComponentVariance, throwExceptionIfFails);
} finally {
bitmap.recycle();
@@ -126,7 +156,8 @@
}
/**
- * Checks whether all the pixels in the specified drawable are of the same specified color.
+ * Checks whether all the pixels in the specified {@link Drawable} are filled with the specific
+ * color.
*
* In case there is a color mismatch, the behavior of this method depends on the
* <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
@@ -136,20 +167,25 @@
public static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull Drawable drawable,
int drawableWidth, int drawableHeight, boolean callSetBounds, @ColorInt int color,
int allowedComponentVariance, boolean throwExceptionIfFails) {
- // Create a bitmap
- Bitmap bitmap = Bitmap.createBitmap(drawableWidth, drawableHeight,
- Bitmap.Config.ARGB_8888);
- // Create a canvas that wraps the bitmap
- Canvas canvas = new Canvas(bitmap);
- if (callSetBounds) {
- // Configure the drawable to have bounds that match the passed size
- drawable.setBounds(0, 0, drawableWidth, drawableHeight);
- }
- // And ask the drawable to draw itself to the canvas / bitmap
- drawable.draw(canvas);
+ // Create a bitmap
+ Bitmap bitmap = Bitmap.createBitmap(drawableWidth, drawableHeight,
+ Bitmap.Config.ARGB_8888);
+ // Create a canvas that wraps the bitmap
+ Canvas canvas = new Canvas(bitmap);
+ if (callSetBounds) {
+ // Configure the drawable to have bounds that match the passed size
+ drawable.setBounds(0, 0, drawableWidth, drawableHeight);
+ } else {
+ // Query the current bounds of the drawable for translation
+ Rect drawableBounds = drawable.getBounds();
+ canvas.translate(-drawableBounds.left, -drawableBounds.top);
+ }
+ // And ask the drawable to draw itself to the canvas / bitmap
+ drawable.draw(canvas);
try {
- assertAllPixelsOfColor(failMessagePrefix, bitmap, drawableWidth, drawableHeight, color,
+ assertAllPixelsOfColor(failMessagePrefix, bitmap,
+ new Rect(0, 0, drawableWidth, drawableHeight), color,
allowedComponentVariance, throwExceptionIfFails);
} finally {
bitmap.recycle();
@@ -157,49 +193,39 @@
}
/**
- * Checks whether all the pixels in the specified bitmap are of the same specified color.
+ * Checks whether all the pixels in the specific rectangular region of the bitmap are filled
+ * with the specific color.
*
* In case there is a color mismatch, the behavior of this method depends on the
* <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
* throw an <code>Exception</code> describing the mismatch. Otherwise this method will call
* <code>Assert.fail</code> with detailed description of the mismatch.
*/
- public static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull Bitmap bitmap,
- int bitmapWidth, int bitmapHeight, @ColorInt int color,
- int allowedComponentVariance, boolean throwExceptionIfFails) {
- int[] rowPixels = new int[bitmapWidth];
- for (int row = 0; row < bitmapHeight; row++) {
+ private static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull Bitmap bitmap,
+ @NonNull Rect region, @ColorInt int color, int allowedComponentVariance,
+ boolean throwExceptionIfFails) {
+ final int bitmapWidth = bitmap.getWidth();
+ final int bitmapHeight = bitmap.getHeight();
+ final int[] rowPixels = new int[bitmapWidth];
+
+ final int startRow = region.top;
+ final int endRow = region.bottom;
+ final int startColumn = region.left;
+ final int endColumn = region.right;
+
+ for (int row = startRow; row < endRow; row++) {
bitmap.getPixels(rowPixels, 0, bitmapWidth, 0, row, bitmapWidth, 1);
- for (int column = 0; column < bitmapWidth; column++) {
- int sourceAlpha = Color.alpha(rowPixels[column]);
- int sourceRed = Color.red(rowPixels[column]);
- int sourceGreen = Color.green(rowPixels[column]);
- int sourceBlue = Color.blue(rowPixels[column]);
-
- int expectedAlpha = Color.alpha(color);
- int expectedRed = Color.red(color);
- int expectedGreen = Color.green(color);
- int expectedBlue = Color.blue(color);
-
- int varianceAlpha = Math.abs(sourceAlpha - expectedAlpha);
- int varianceRed = Math.abs(sourceRed - expectedRed);
- int varianceGreen = Math.abs(sourceGreen - expectedGreen);
- int varianceBlue = Math.abs(sourceBlue - expectedBlue);
-
- boolean isColorMatch = (varianceAlpha <= allowedComponentVariance)
- && (varianceRed <= allowedComponentVariance)
- && (varianceGreen <= allowedComponentVariance)
- && (varianceBlue <= allowedComponentVariance);
-
- if (!isColorMatch) {
+ for (int column = startColumn; column < endColumn; column++) {
+ @ColorInt int colorAtCurrPixel = rowPixels[column];
+ if (!areColorsTheSameWithTolerance(color, colorAtCurrPixel,
+ allowedComponentVariance)) {
String mismatchDescription = failMessagePrefix
- + ": expected all drawable colors to be ["
- + expectedAlpha + "," + expectedRed + ","
- + expectedGreen + "," + expectedBlue
- + "] but at position (" + row + "," + column + ") out of ("
- + bitmapWidth + "," + bitmapHeight + ") found ["
- + sourceAlpha + "," + sourceRed + ","
- + sourceGreen + "," + sourceBlue + "]";
+ + ": expected all bitmap colors in rectangle [l="
+ + startColumn + ", t=" + startRow + ", r=" + endColumn
+ + ", b=" + endRow + "] to be " + formatColorToHex(color)
+ + " but at position (" + row + "," + column + ") out of ("
+ + bitmapWidth + "," + bitmapHeight + ") found "
+ + formatColorToHex(colorAtCurrPixel);
if (throwExceptionIfFails) {
throw new RuntimeException(mismatchDescription);
} else {
@@ -209,4 +235,179 @@
}
}
}
+
+ /**
+ * Checks whether the center pixel in the specified bitmap is of the same specified color.
+ *
+ * In case there is a color mismatch, the behavior of this method depends on the
+ * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
+ * throw an <code>Exception</code> describing the mismatch. Otherwise this method will call
+ * <code>Assert.fail</code> with detailed description of the mismatch.
+ */
+ public static void assertCenterPixelOfColor(String failMessagePrefix, @NonNull Bitmap bitmap,
+ @ColorInt int color,
+ int allowedComponentVariance, boolean throwExceptionIfFails) {
+ final int centerX = bitmap.getWidth() / 2;
+ final int centerY = bitmap.getHeight() / 2;
+ final @ColorInt int colorAtCenterPixel = bitmap.getPixel(centerX, centerY);
+ if (!areColorsTheSameWithTolerance(color, colorAtCenterPixel,
+ allowedComponentVariance)) {
+ String mismatchDescription = failMessagePrefix
+ + ": expected all drawable colors to be "
+ + formatColorToHex(color)
+ + " but at position (" + centerX + "," + centerY + ") out of ("
+ + bitmap.getWidth() + "," + bitmap.getHeight() + ") found"
+ + formatColorToHex(colorAtCenterPixel);
+ if (throwExceptionIfFails) {
+ throw new RuntimeException(mismatchDescription);
+ } else {
+ Assert.fail(mismatchDescription);
+ }
+ }
+ }
+
+ /**
+ * Formats the passed integer-packed color into the #AARRGGBB format.
+ */
+ public static String formatColorToHex(@ColorInt int color) {
+ return String.format("#%08X", (0xFFFFFFFF & color));
+ }
+
+ /**
+ * Compares two integer-packed colors to be equal, each component within the specified
+ * allowed variance. Returns <code>true</code> if the two colors are sufficiently equal
+ * and <code>false</code> otherwise.
+ */
+ private static boolean areColorsTheSameWithTolerance(@ColorInt int expectedColor,
+ @ColorInt int actualColor, int allowedComponentVariance) {
+ int sourceAlpha = Color.alpha(actualColor);
+ int sourceRed = Color.red(actualColor);
+ int sourceGreen = Color.green(actualColor);
+ int sourceBlue = Color.blue(actualColor);
+
+ int expectedAlpha = Color.alpha(expectedColor);
+ int expectedRed = Color.red(expectedColor);
+ int expectedGreen = Color.green(expectedColor);
+ int expectedBlue = Color.blue(expectedColor);
+
+ int varianceAlpha = Math.abs(sourceAlpha - expectedAlpha);
+ int varianceRed = Math.abs(sourceRed - expectedRed);
+ int varianceGreen = Math.abs(sourceGreen - expectedGreen);
+ int varianceBlue = Math.abs(sourceBlue - expectedBlue);
+
+ boolean isColorMatch = (varianceAlpha <= allowedComponentVariance)
+ && (varianceRed <= allowedComponentVariance)
+ && (varianceGreen <= allowedComponentVariance)
+ && (varianceBlue <= allowedComponentVariance);
+
+ return isColorMatch;
+ }
+
+ /**
+ * Composite two potentially translucent colors over each other and returns the result.
+ */
+ public static int compositeColors(@ColorInt int foreground, @ColorInt int background) {
+ int bgAlpha = Color.alpha(background);
+ int fgAlpha = Color.alpha(foreground);
+ int a = compositeAlpha(fgAlpha, bgAlpha);
+
+ int r = compositeComponent(Color.red(foreground), fgAlpha,
+ Color.red(background), bgAlpha, a);
+ int g = compositeComponent(Color.green(foreground), fgAlpha,
+ Color.green(background), bgAlpha, a);
+ int b = compositeComponent(Color.blue(foreground), fgAlpha,
+ Color.blue(background), bgAlpha, a);
+
+ return Color.argb(a, r, g, b);
+ }
+
+ private static int compositeAlpha(int foregroundAlpha, int backgroundAlpha) {
+ return 0xFF - (((0xFF - backgroundAlpha) * (0xFF - foregroundAlpha)) / 0xFF);
+ }
+
+ private static int compositeComponent(int fgC, int fgA, int bgC, int bgA, int a) {
+ if (a == 0) return 0;
+ return ((0xFF * fgC * fgA) + (bgC * bgA * (0xFF - fgA))) / (a * 0xFF);
+ }
+
+ public static CharSequence sameCharSequence(final CharSequence expected) {
+ return argThat(new BaseMatcher<CharSequence>() {
+ @Override
+ public boolean matches(Object o) {
+ if (o instanceof CharSequence) {
+ return TextUtils.equals(expected, (CharSequence) o);
+ }
+ return false;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("doesn't match " + expected);
+ }
+ });
+ }
+
+ public static Editable sameEditable(final Editable expected) {
+ return argThat(new BaseMatcher<Editable>() {
+ @Override
+ public boolean matches(Object o) {
+ if (o instanceof Editable) {
+ return TextUtils.equals(expected, (Editable) o);
+ }
+ return false;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("doesn't match " + expected);
+ }
+ });
+ }
+
+ public static ColorStateList colorStateListOf(final @ColorInt int color) {
+ return argThat(new BaseMatcher<ColorStateList>() {
+ @Override
+ public boolean matches(Object o) {
+ if (o instanceof ColorStateList) {
+ final ColorStateList actual = (ColorStateList) o;
+ return (actual.getColors().length == 1) && (actual.getDefaultColor() == color);
+ }
+ return false;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("doesn't match " + formatColorToHex(color));
+ }
+ });
+ }
+
+ public static int dpToPx(Context context, int dp) {
+ final float density = context.getResources().getDisplayMetrics().density;
+ return (int) (dp * density + 0.5f);
+ }
+
+ private static String arrayToString(final long[] array) {
+ final StringBuffer buffer = new StringBuffer();
+ if (array == null) {
+ buffer.append("null");
+ } else {
+ buffer.append("[");
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(", ");
+ }
+ buffer.append(array[i]);
+ }
+ buffer.append("]");
+ }
+ return buffer.toString();
+ }
+
+ public static void assertIdentical(final long[] expected, final long[] actual) {
+ if (!Arrays.equals(expected, actual)) {
+ Assert.fail("Expected " + arrayToString(expected) + ", actual "
+ + arrayToString(actual));
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/tests/widget/src/android/widget/cts/util/TestUtilsMatchers.java b/tests/tests/widget/src/android/widget/cts/util/TestUtilsMatchers.java
new file mode 100644
index 0000000..3664bc4
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/util/TestUtilsMatchers.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package android.widget.cts.util;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+import java.util.List;
+
+public class TestUtilsMatchers {
+ /**
+ * Returns a matcher that matches lists of int values that are in ascending order.
+ */
+ public static Matcher<List<Integer>> inAscendingOrder() {
+ return new TypeSafeMatcher<List<Integer>>() {
+ private String mFailedDescription;
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(mFailedDescription);
+ }
+
+ @Override
+ protected boolean matchesSafely(List<Integer> item) {
+ int itemCount = item.size();
+
+ if (itemCount >= 2) {
+ for (int i = 0; i < itemCount - 1; i++) {
+ int curr = item.get(i);
+ int next = item.get(i + 1);
+
+ if (curr > next) {
+ mFailedDescription = "Values should increase between #" + i +
+ ":" + curr + " and #" + (i + 1) + ":" + next;
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+ };
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/util/ViewTestUtils.java b/tests/tests/widget/src/android/widget/cts/util/ViewTestUtils.java
index e9ef867..69c788b 100644
--- a/tests/tests/widget/src/android/widget/cts/util/ViewTestUtils.java
+++ b/tests/tests/widget/src/android/widget/cts/util/ViewTestUtils.java
@@ -16,14 +16,16 @@
package android.widget.cts.util;
-import junit.framework.Assert;
-
import android.app.Instrumentation;
+import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnDrawListener;
+import junit.framework.Assert;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -34,8 +36,8 @@
public class ViewTestUtils {
/**
- * Runs the specified Runnable on the main thread and ensures that the
- * specified View's tree is drawn before returning.
+ * Runs the specified Runnable on the main thread and ensures that the specified View's tree is
+ * drawn before returning.
*
* @param instrumentation the instrumentation used to run the test
* @param view the view whose tree should be drawn before returning
@@ -72,4 +74,138 @@
throw new RuntimeException(e);
}
}
-}
+
+ /**
+ * Emulates a tap in the center of the passed {@link View}.
+ *
+ * @param instrumentation the instrumentation used to run the test
+ * @param view the view to "tap"
+ */
+ public static void emulateTapOnViewCenter(Instrumentation instrumentation, View view) {
+ emulateTapOnScreen(instrumentation, view, view.getWidth() / 2, view.getHeight() / 2);
+ }
+
+ /**
+ * Emulates a tap on a point relative to the top-left corner of the passed {@link View}. Offset
+ * parameters are used to compute the final screen coordinates of the tap point.
+ *
+ * @param instrumentation the instrumentation used to run the test
+ * @param anchorView the anchor view to determine the tap location on the screen
+ * @param offsetX extra X offset for the tap
+ * @param offsetY extra Y offset for the tap
+ */
+ public static void emulateTapOnScreen(Instrumentation instrumentation, View anchorView,
+ int offsetX, int offsetY) {
+ // Use instrumentation to emulate a tap on the spinner to bring down its popup
+ final int[] viewOnScreenXY = new int[2];
+ anchorView.getLocationOnScreen(viewOnScreenXY);
+ int emulatedTapX = viewOnScreenXY[0] + offsetX;
+ int emulatedTapY = viewOnScreenXY[1] + offsetY;
+
+ // Inject DOWN event
+ long downTime = SystemClock.uptimeMillis();
+ MotionEvent eventDown = MotionEvent.obtain(
+ downTime, downTime, MotionEvent.ACTION_DOWN, emulatedTapX, emulatedTapY, 1);
+ instrumentation.sendPointerSync(eventDown);
+
+ // Inject MOVE event
+ long moveTime = SystemClock.uptimeMillis();
+ MotionEvent eventMove = MotionEvent.obtain(
+ moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedTapX, emulatedTapY, 1);
+ instrumentation.sendPointerSync(eventMove);
+
+ // Inject UP event
+ long upTime = SystemClock.uptimeMillis();
+ MotionEvent eventUp = MotionEvent.obtain(
+ upTime, upTime, MotionEvent.ACTION_UP, emulatedTapX, emulatedTapY, 1);
+ instrumentation.sendPointerSync(eventUp);
+
+ // Wait for the system to process all events in the queue
+ instrumentation.waitForIdleSync();
+ }
+
+ /**
+ * Emulates a drag gesture across the screen.
+ *
+ * @param instrumentation the instrumentation used to run the test
+ * @param dragStartX Start X of the emulated drag gesture
+ * @param dragStartY Start Y of the emulated drag gesture
+ * @param dragAmountX X amount of the emulated drag gesture
+ * @param dragAmountY Y amount of the emulated drag gesture
+ */
+ public static void emulateDragGesture(Instrumentation instrumentation,
+ int dragStartX, int dragStartY, int dragAmountX, int dragAmountY) {
+ // Inject DOWN event
+ long downTime = SystemClock.uptimeMillis();
+ MotionEvent eventDown = MotionEvent.obtain(
+ downTime, downTime, MotionEvent.ACTION_DOWN, dragStartX, dragStartY, 1);
+ instrumentation.sendPointerSync(eventDown);
+
+ // Inject a sequence of MOVE events that emulate a "swipe down" gesture
+ final int moveEventCount = 20;
+ for (int i = 0; i < moveEventCount; i++) {
+ long moveTime = SystemClock.uptimeMillis();
+ final int moveX = dragStartX + dragAmountX * i / moveEventCount;
+ final int moveY = dragStartY + dragAmountY * i / moveEventCount;
+ MotionEvent eventMove = MotionEvent.obtain(
+ moveTime, moveTime, MotionEvent.ACTION_MOVE, moveX, moveY, 1);
+ instrumentation.sendPointerSync(eventMove);
+ // sleep for a bit to emulate a 2-second swipe
+ SystemClock.sleep(2000 / moveEventCount);
+ }
+
+ // Inject UP event
+ long upTime = SystemClock.uptimeMillis();
+ MotionEvent eventUp = MotionEvent.obtain(
+ upTime, upTime, MotionEvent.ACTION_UP, dragStartX + dragAmountX,
+ dragStartY + dragAmountY, 1);
+ instrumentation.sendPointerSync(eventUp);
+
+ // Wait for the system to process all events in the queue
+ instrumentation.waitForIdleSync();
+ }
+
+ /**
+ * Emulates a long click in the center of the passed {@link View}.
+ *
+ * @param instrumentation the instrumentation used to run the test
+ * @param view the view to "long click"
+ * @param extraWaitMs the duration of emulated long click in milliseconds starting
+ * after system-level long press timeout.
+ */
+ public static void emulateLongClick(Instrumentation instrumentation, View view,
+ long extraWaitMs) {
+ // Use instrumentation to emulate a tap on the spinner to bring down its popup
+ final int[] viewOnScreenXY = new int[2];
+ view.getLocationOnScreen(viewOnScreenXY);
+ int emulatedTapX = viewOnScreenXY[0] + view.getWidth() / 2;
+ int emulatedTapY = viewOnScreenXY[1] + view.getHeight() / 2;
+
+ // Inject DOWN event
+ long downTime = SystemClock.uptimeMillis();
+ MotionEvent eventDown = MotionEvent.obtain(
+ downTime, downTime, MotionEvent.ACTION_DOWN, emulatedTapX, emulatedTapY, 1);
+ instrumentation.sendPointerSync(eventDown);
+
+ // Inject MOVE event
+ long moveTime = SystemClock.uptimeMillis();
+ MotionEvent eventMove = MotionEvent.obtain(
+ moveTime, moveTime, MotionEvent.ACTION_MOVE, emulatedTapX, emulatedTapY, 1);
+ instrumentation.sendPointerSync(eventMove);
+
+ try {
+ Thread.sleep(ViewConfiguration.getLongPressTimeout() + extraWaitMs);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ // Inject UP event
+ long upTime = SystemClock.uptimeMillis();
+ MotionEvent eventUp = MotionEvent.obtain(
+ upTime, upTime, MotionEvent.ACTION_UP, emulatedTapX, emulatedTapY, 1);
+ instrumentation.sendPointerSync(eventUp);
+
+ // Wait for the system to process all events in the queue
+ instrumentation.waitForIdleSync();
+ }
+}
\ No newline at end of file
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index e1eeba6..18c3762 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -45,17 +45,6 @@
<option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaWidgetId" />
<option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaWidgetIds" />
- <!-- b/21668302 -->
- <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.AssistantContentViewTest#testAssistantContentViewDimens" />
- <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.ExtraAssistDataTest#testAssistContentAndAssistData" />
- <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.FocusChangeTest#testLayerCausesUnderlyingActivityToLoseFocus" />
- <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.LargeViewHierarchyTest#testTextView" />
- <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.ScreenshotTest#testBlueScreenshot" />
- <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.ScreenshotTest#testGreenScreenshot" />
- <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.ScreenshotTest#testRedScreenshot" />
- <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.TextViewTest#testTextView" />
- <option name="compatibility:exclude-filter" value="CtsAssistTestCases android.assist.cts.WebViewTest#testWebView" />
-
<!-- b/23776099 -->
<option name="compatibility:exclude-filter" value="CtsCallLogTestCases" />
diff --git a/tools/utils/buildCts.py b/tools/utils/buildCts.py
index f983b15..bd5fc90 100755
--- a/tools/utils/buildCts.py
+++ b/tools/utils/buildCts.py
@@ -522,15 +522,6 @@
'android.alarmclock.cts.SetAlarmTest#testAll',
'android.alarmclock.cts.SnoozeAlarmTest#testAll',
],
- 'android.assist' : [
- 'android.assist.cts.AssistantContentViewTest',
- 'android.assist.cts.ExtraAssistDataTest',
- 'android.assist.cts.FocusChangeTest',
- 'android.assist.cts.LargeViewHierarchyTest',
- 'android.assist.cts.ScreenshotTest',
- 'android.assist.cts.TextViewTest',
- 'android.assist.cts.WebViewTest',
- ],
'android.calllog' : [
'android.calllog.cts.CallLogBackupTest#testSingleCallBackup',
],